<?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: Jula Markova</title>
    <description>The latest articles on DEV Community by Jula Markova (@jula-markova).</description>
    <link>https://dev.to/jula-markova</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3937734%2F17aedaad-5bbb-49c9-b5eb-73450ec3a042.webp</url>
      <title>DEV Community: Jula Markova</title>
      <link>https://dev.to/jula-markova</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jula-markova"/>
    <language>en</language>
    <item>
      <title>Four Ways a Batch Runner Can Believe It Already Finished</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Tue, 01 Sep 2026 22:11:49 +0000</pubDate>
      <link>https://dev.to/jula-markova/four-ways-a-batch-runner-can-believe-it-already-finished-4kcd</link>
      <guid>https://dev.to/jula-markova/four-ways-a-batch-runner-can-believe-it-already-finished-4kcd</guid>
      <description>&lt;p&gt;On 16 March 2026 the batch runner for our content pipeline landed in a single commit. That commit already contained a resume flag, a state log with per-item status, error classification, a quota pause, and a lock file. Resumability was not bolted on after it hurt. It was there on day one, and it still did not work for another three months.&lt;/p&gt;

&lt;p&gt;That gap is the article.&lt;/p&gt;

&lt;p&gt;When people write about resumable AI systems, they usually mean an agent remembering a conversation across turns: threads, checkpointers, replaying a graph from a saved node. This is the other thing. A batch pipeline that has to know which work is already finished, across separate runs and across two different machines.&lt;/p&gt;

&lt;p&gt;The order in which we built it is not flattering, so I will put it first. Eleven days before the runner existed, we had a &lt;a href="https://www.bestaiweb.ai/glossary/circuit-breaker/" rel="noopener noreferrer"&gt;circuit breaker&lt;/a&gt; (stop after three consecutive quota failures) and a shutdown path that kills child processes when the parent is interrupted instead of orphaning them. That is survival of one call, not resumability. Four days after the runner, we shipped a retry that continued a half-written file instead of regenerating it, which is the classic confusion between the two: &lt;a href="https://www.bestaiweb.ai/glossary/llm-fallback-and-retry-patterns/" rel="noopener noreferrer"&gt;retry patterns&lt;/a&gt; are about surviving a call that failed, resume is about not paying again for a call that already succeeded. We built them in that order, and for a while I assumed the second came free with the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the runner actually tracks
&lt;/h2&gt;

&lt;p&gt;Two axes, kept deliberately separate.&lt;/p&gt;

&lt;p&gt;An entity (for us: one topic that owns a set of articles) is in exactly one of five states:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pending&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;not started, or reset after a dead run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;running&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;claimed by the current run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;done&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;all planned output exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;failed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;stopped for a reason that waiting will not fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paused&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;stopped for a reason that waiting &lt;em&gt;will&lt;/em&gt; fix&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A failure additionally carries one of six categories: &lt;code&gt;timeout&lt;/code&gt;, &lt;code&gt;quota&lt;/code&gt;, &lt;code&gt;validation&lt;/code&gt;, &lt;code&gt;phase_error&lt;/code&gt;, &lt;code&gt;planning_error&lt;/code&gt;, &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Keeping the category off the state axis is what lets &lt;code&gt;paused&lt;/code&gt; and &lt;code&gt;failed&lt;/code&gt; be different verbs at all. Quota exhaustion is not a defect. It is the system being told to come back later, which is exactly the distinction that separates &lt;a href="https://www.bestaiweb.ai/glossary/agent-error-handling-and-recovery/" rel="noopener noreferrer"&gt;pausing from failing&lt;/a&gt; in any batch that talks to a metered API. A validation error is the opposite: waiting a thousand years will not change a deterministic verdict, so it stops the run for a human.&lt;/p&gt;

&lt;p&gt;One detail that only shows up once a run has actually been killed: it leaves its entities frozen in &lt;code&gt;running&lt;/code&gt;, and nothing will ever move them on its own. So a resumed run sweeps stale &lt;code&gt;running&lt;/code&gt; back to &lt;code&gt;pending&lt;/code&gt; before it schedules anything. Note where that reclaim stops: it covers entity state, not the lock file the dead run also left behind. Those needed two different owners, and we found that out the hard way.&lt;/p&gt;

&lt;h2&gt;
  
  
  22 June: four holes in the same mechanism, all in one day
&lt;/h2&gt;

&lt;p&gt;An audit had turned up four independent ways the resumable runner could be silently wrong, and all four fixes landed in one day. Not one bug with four symptoms. Four bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(a)&lt;/strong&gt; A quota error came back as an empty result instead of raising. The parallel aggregator treated it as a value, so the batch reported success, missing content was recorded as produced, and the run kept going. This one gets its own section below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(b)&lt;/strong&gt; Three separate places in the stack each recognised &lt;a href="https://www.bestaiweb.ai/glossary/rate-limiting/" rel="noopener noreferrer"&gt;rate-limit&lt;/a&gt; errors their own way, with their own string matching. What one layer flagged, another missed, and which one you hit depended on where the error happened to surface. The fix was not to add the missing phrases in three places. It was to delete two of the matchers and have everything ask the same one, which is the same move as killing &lt;a href="https://www.bestaiweb.ai/anatomy-of-a-flaky-ai-agent/" rel="noopener noreferrer"&gt;a whole class of error rather than the instance in front of you&lt;/a&gt;. We had learned the general shape of this before, when a single output contract had to hold identically across &lt;a href="https://www.bestaiweb.ai/llm-structured-output-three-backends/" rel="noopener noreferrer"&gt;three different model backends&lt;/a&gt;: if a rule can drift between implementations, it eventually will.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(c)&lt;/strong&gt; A corrupted state file was read as "fresh start". Not as an error. As zero progress, cheerfully, and then we paid for everything again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(d)&lt;/strong&gt; The lock had a check-then-write window between "is anyone holding this" and "I am holding this", wide enough for two runners to both walk through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where failures go to become data
&lt;/h2&gt;

&lt;p&gt;Hole (a) is the one worth stealing, because the shape is everywhere.&lt;/p&gt;

&lt;p&gt;Our generation step launches many agents in parallel for one topic and waits for all of them, collecting outcomes instead of letting the first failure escape. Every language has this primitive, and using it is correct here: one agent dying should not orphan its seventeen-odd siblings mid-flight.&lt;/p&gt;

&lt;p&gt;But our runners, on permanent quota exhaustion, &lt;em&gt;returned&lt;/em&gt; an empty result rather than raising. An empty result is a value. Values pass through a gather-all aggregator as data, not as alarms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;before:
  run(prompt) -&amp;gt; Result          # exhausted quota yields Result(text="")
  batch = gather_all(runs)       # every entry is fulfilled
  =&amp;gt; batch reports success
  =&amp;gt; caller records each item as produced
  =&amp;gt; run continues into the next topic, against a closed window

after:
  run(prompt) raises QuotaExhausted
  phase re-raises it past the aggregator
  per-topic loop recognises the signature
  =&amp;gt; entity moves to paused, not failed
  =&amp;gt; the whole run stops and notifies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bug was not "we forgot to check for errors". We checked. The check ran against a result object that had been handed a successful-looking shape by a layer that had already given up.&lt;/p&gt;

&lt;p&gt;If a failure has to travel through an aggregator, decide explicitly how it survives the trip. Raise, or wrap it in something the aggregator cannot flatten into a value. Deciding by accident means deciding "it becomes data".&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure mode, category, reaction
&lt;/h2&gt;

&lt;p&gt;The table we now actually operate by:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What happened&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;What the runner does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quota exhausted&lt;/td&gt;
&lt;td&gt;&lt;code&gt;quota&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pause the whole run, notify a human, resume later. Waiting &lt;em&gt;is&lt;/em&gt; the fix.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deterministic check failed&lt;/td&gt;
&lt;td&gt;&lt;code&gt;validation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stop immediately. No amount of waiting changes a verdict.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timeout, or a bare &lt;code&gt;exit code 1&lt;/code&gt; with no explanation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;timeout&lt;/code&gt; / &lt;code&gt;unknown&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Back off and probe. Often this is a filled quota window wearing an unhelpful error.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crashed run left a lock behind&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;The runner reclaims stale entity state but not its own lock file; the supervising wrapper clears a lock whose owner process is gone.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last row deserves honesty. File-based locking on one machine is not distributed coordination, and I am not going to pretend otherwise. What the next section buys us is narrower than it may sound: sequential runs on two machines agree on what is already done, as long as each one pulls the committed output before it starts. Two runs started at the same time are not coordinated at all, and nothing in this design stops them from generating the same work twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  24 June: "done" stopped being something we stored
&lt;/h2&gt;

&lt;p&gt;The real fix was not a better flag. It was deleting the authority of the state file.&lt;/p&gt;

&lt;p&gt;Before: "is this topic finished?" was answered by reading a local, untracked progress file. After: it is &lt;em&gt;derived&lt;/em&gt; from two signals that are committed to the repository.&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="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;planned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;slugs&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="n"&gt;promises&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;planned&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;
           &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;every&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;planned&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;content_dir&lt;/span&gt;&lt;span class="o"&gt;/&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state file still exists. It was demoted to a cache, rebuilt from that derivation, and no longer trusted when the two disagree.&lt;/p&gt;

&lt;p&gt;Two consequences follow, and only the second one was obvious to us at the time.&lt;/p&gt;

&lt;p&gt;The same committed inputs produce the same answer on any machine. I work on two computers. Machine B pulls, derives, and skips exactly what machine A generated, with no state synchronisation, no shared database, and no reliance on A's local files. Note the word &lt;em&gt;pulls&lt;/em&gt;: this buys agreement between runs that happen one after another, not mutual exclusion between runs that happen at once.&lt;/p&gt;

&lt;p&gt;And the worst pre-fix failure mode was never corruption. It was waste. On a fresh clone, everything looked undone, so a run would burn an entire quota window re-researching roughly a hundred already-finished topics before it ever touched new work. Nothing crashed. Nothing warned. The run just spent the night rebuilding the past.&lt;/p&gt;

&lt;p&gt;The honest limitation, stated immediately: this checks &lt;strong&gt;existence only&lt;/strong&gt;. No hash, no size, no content inspection. An empty file passes. That is deliberate, because it is the cheapest test that behaves identically on every machine and requires no extra state, but it is a real limit, and the section after next is about where it bites.&lt;/p&gt;

&lt;h2&gt;
  
  
  26 June: it recovered without me
&lt;/h2&gt;

&lt;p&gt;The unattended overnight loop hit a closed quota window, waited, and came back on its own. Article count went from 640 to 646 while I was asleep. No human touched it.&lt;/p&gt;

&lt;p&gt;It reads no usage gauge, because that number is not available programmatically. So the strategy is deliberately dumb: generate until the wall, pause, probe, continue.&lt;/p&gt;

&lt;p&gt;It had to learn two things the hard way. First, a closed window frequently surfaces as a plain &lt;code&gt;exit code 1&lt;/code&gt; with no quota signature anywhere in it, which is why &lt;code&gt;unknown&lt;/code&gt; and &lt;code&gt;timeout&lt;/code&gt; route to back-off rather than to a stop.&lt;/p&gt;

&lt;p&gt;Second, blindly retrying into a closed window is expensive in a way that is invisible until you count. On 27 June one topic re-launched its full batch of around eighteen agents about twelve times, in the order of 150 process launches, every one of them dying on the wall. The fix was one cheap probe call before each round whose only output is an exit code: window open, quota exhausted, inconclusive. That shape matters more than it looks. Because the answer is an exit code, the shell wrapper that schedules the rounds never needs to parse an error message, and therefore cannot grow a second, subtly different copy of the quota-recognition logic we had just finished unifying.&lt;/p&gt;

&lt;h2&gt;
  
  
  4 August: the rule left the pipeline
&lt;/h2&gt;

&lt;p&gt;By August this stopped being pipeline architecture and became a standing rule for every throwaway helper script I write: &lt;strong&gt;one file per paid call, and on startup skip whatever already exists on disk.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It earned that promotion. A 360-call collection was interrupted (the run record puts it around call 186), restarted at 187, and finished without paying again for the calls it had already made. One existence check, one file per call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is still wrong
&lt;/h2&gt;

&lt;p&gt;The general theory of &lt;a href="https://www.bestaiweb.ai/prerequisites-for-building-resilient-agents-failure-modes-idempotency-and-durable-execution/" rel="noopener noreferrer"&gt;failure modes, idempotency and durable execution&lt;/a&gt; is well covered by people who know it far better than I do. What follows is specifically where &lt;em&gt;our&lt;/em&gt; instance of it does not hold up, both found when a reviewer pushed on an earlier version of this article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output files are not written atomically.&lt;/strong&gt; Our two run state files are: temp file, then rename. The generated articles are not. They go through a plain write. So a crash mid-write leaves a partial file, and the existence check accepts it as finished, forever, without complaint. This is not the same half-written file the retry knows how to continue: that one sits in the working area, where being unfinished is the expected state. This one has already crossed into the published tree, where existence is the whole proof. The boundary between "in progress" and "done" is that crossing, and the crossing is not atomic. We replaced one kind of false "done" with a rarer kind. The fix is the trick we already use one layer down: write to a temp file, then rename, so the file either exists complete or does not exist at all. There is even a central writer class that every generated file could pass through, which makes this a one-place change rather than a hunt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"One file per call" is checkpointing, not idempotence.&lt;/strong&gt; Our identity for a piece of work is the slug plus a hash of the content plan. Nothing else. Change the template, change the prompt, change the model, and nothing invalidates: the old file causes a skip, and the run reports success while serving work produced by a system that no longer exists. There is partial invalidation at the article level (the plan hash, a 14-day freshness window on research, re-verification when article or research content changed), but none of it covers prompt or template versions. If you build this, put the version of &lt;em&gt;everything that shapes the output&lt;/em&gt; into the identity, or you will confidently serve stale work.&lt;/p&gt;

&lt;p&gt;Worth separating one thing out: resumability answers "don't redo finished work". A completely different set of rules answers "when you do redo it, don't destroy what appeared in the meantime". We got that second part wrong too, in its own way, and it is its own article.&lt;/p&gt;

&lt;h2&gt;
  
  
  When none of this is worth building
&lt;/h2&gt;

&lt;p&gt;The strongest objection is that resumability is overengineering, and a stateless rerun is enough. For a short, cheap, single-machine job that is simply correct, and checkpointing infrastructure is a tax on a problem you do not have.&lt;/p&gt;

&lt;p&gt;Three conditions flip it. Paid calls make "rerun is free" false, and the price is exact and boring: our hundred re-researched topics. Multi-hour quota windows turn stopping into an operating mode rather than a fault, so "just run it again" is not a thing the operator can do at will. And the cheapest working form is not a framework, a queue, or a workflow engine. It is one existence check and one file per call. If the cheap version is off the table, the objection is usually arguing against something nobody proposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do not know
&lt;/h2&gt;

&lt;p&gt;The existence check accepts an empty file, and I have not fixed it yet. I have no counter for how often the derived skip actually saves a run, so I cannot tell you the value in hours or euros. The interrupted-collection numbers come from a run record, not from a log I can re-read today. The overnight self-recovery is n=1. And the crash paths are only half tested. There are tests for a corrupted state file and for the atomicity of the state write, which is how those two ended up trustworthy. There is nothing for a kill during a content write, nothing for two runs starting at once, nothing for a plan that changed under a finished topic. Some of what is described here we found by reading the code, some by a reviewer pushing on this article, and the rest the least efficient way available, by it happening to us. The pattern is not subtle: the paths with tests stopped surprising us. That is the honest next step.&lt;/p&gt;

&lt;p&gt;Here is the bet I would defend. Resumability is not a property of a run. It is a property of where the truth about finished work lives, and that truth has to be durable, shared, and independently verifiable. For us the authoritative store happens to be the repository, only because our output is files that get committed anyway. For you it may be a database, an object store, an event log, or a workflow engine. The store is an implementation detail. The three adjectives are not.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm an IT analyst who spends her days working with Claude Code on &lt;a href="https://www.bestaiweb.ai/" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt;, an AI-written publication about AI engineering. I'm not a software engineer by training, and this pipeline's scars have taught me more than any tutorial I've read. The best experiments are the ones you can't keep to yourself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: the pipeline, the commits and the numbers are ours; the drafting of this article was done with AI assistance — the same collaboration the article describes.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>devjournal</category>
      <category>backend</category>
    </item>
    <item>
      <title>LLM Evaluation for Software Engineers Without an ML Background: the 90+ Checks We Actually Run</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Wed, 26 Aug 2026 10:06:14 +0000</pubDate>
      <link>https://dev.to/jula-markova/llm-evaluation-for-software-engineers-without-an-ml-background-the-90-checks-we-actually-run-5fp9</link>
      <guid>https://dev.to/jula-markova/llm-evaluation-for-software-engineers-without-an-ml-background-the-90-checks-we-actually-run-5fp9</guid>
      <description>&lt;p&gt;I run a content pipeline where AI writes every article — and where AI is, on principle, not trusted. Before any piece ships to our site, it survives more than ninety separate verifications: research checks, fact cross-referencing, a deterministic validator with dozens of rules, integration guards. We never sat down and said "let's build an LLM evaluation harness." We sat down and said "let's not publish embarrassing text," and then kept adding checks every time something embarrassing nearly got through.&lt;/p&gt;

&lt;p&gt;It took me surprisingly long to notice that what we'd accumulated &lt;em&gt;is&lt;/em&gt; an &lt;a href="https://www.bestaiweb.ai/glossary/evaluation-harness/" rel="noopener noreferrer"&gt;evaluation harness&lt;/a&gt; — the same category of thing the eval frameworks and judge models are selling, just grown organically around one production system. This is a tour of what those metrics actually are, in the order they run — and of the day the whole stack taught me its own limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shape of the Stack: Code First, Judgment Last
&lt;/h2&gt;

&lt;p&gt;The ninety-plus number sounds inflated until you itemize it, so let me itemize it. Before a single sentence of an article exists, the research that feeds it passes about twenty checks of its own — is the fact base structurally sound, are the sources real and reachable, is anything suspicious hiding in fetched web content. After the article is written, every factual claim in it gets cross-referenced against the researched fact sheet — around twenty more verifications, this time performed by an AI agent. Then a deterministic validator runs roughly thirty-nine atomic rules over the finished text. Finally, eight guards fire during integration into the site build. Add the self-correction re-checks and you're past ninety verifications for one article. A full subject — six articles, ten glossary entries, one hub page — crosses a thousand.&lt;/p&gt;

&lt;p&gt;The architecture behind that pile is one sentence long: &lt;strong&gt;anything code can verify, code verifies; the LLM judges only what code cannot.&lt;/strong&gt; It's the single most load-bearing decision in the pipeline, and we made it early, mostly out of cheapness — which is also the honest answer to anyone asking about the ROI of LLM evaluation. Deterministic checks cost nothing, run in seconds, and give the same answer every time. LLM judgment costs money, takes minutes, and drifts. So the expensive judge should only ever see questions the cheap rules can't answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer One: What a Regex Can Catch, a Regex Should Catch
&lt;/h2&gt;

&lt;p&gt;The deterministic layer is unglamorous and does most of the work. Structure: required sections present, headings unique, frontmatter complete. Ranges: word counts inside bounds, image alt-texts within limits. Forbidden patterns: the vocabulary that makes text smell machine-written — we call the category "AI-tell words" — and something nastier we call "scaffolding leaks," where a fragment of the internal writing instructions bleeds into the published prose ("as mentioned in the brief…"). Link integrity, metadata lengths, image references. Thirty check functions in the main validator; the variant for our developer-orientation articles runs thirty-four checks.&lt;/p&gt;

&lt;p&gt;None of this measures whether an article is &lt;em&gt;good&lt;/em&gt;. That's the point. This layer defines a floor — the set of failures that should never require human attention again, because a machine catches them identically every single time. If you're building any LLM evaluation setup and your judge model is checking whether required sections exist, you've put the expensive instrument on the cheap problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer Two: A Judge With the Narrowest Possible Job Description
&lt;/h2&gt;

&lt;p&gt;There is exactly one place in the pipeline where LLM judgment gates content, and its job description is deliberately tiny: claim verification. The agent takes each factual claim in the finished article and asks one closed question — &lt;em&gt;is this claim supported by the fact sheet we researched?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer is one of five labels, and the three beyond the obvious pair are where the value hides. A claim can &lt;strong&gt;match&lt;/strong&gt; the research. It can &lt;strong&gt;distort&lt;/strong&gt; it — "$24" written as "$25", "34%" written as "nearly 40%". It can be &lt;strong&gt;invented&lt;/strong&gt;, with no basis in the fact sheet at all. It can &lt;strong&gt;ignore a caution&lt;/strong&gt;: the research explicitly noted "enterprise pricing not publicly available" and the article states a price anyway. Or it can be &lt;strong&gt;missing attribution&lt;/strong&gt; — a real number, correctly copied, presented as if it were common knowledge. Anything scored high or medium severity fails the article into a bounded self-correction loop; what can't be fixed gets surfaced for a human.&lt;/p&gt;

&lt;p&gt;That fourth label is the one I'd recommend to anyone building this. Invented facts are the failure everyone designs for. Quietly promoting a known unknown into a stated fact is the one that actually ships.&lt;/p&gt;

&lt;p&gt;The narrowness is the design. The research on &lt;a href="https://www.bestaiweb.ai/glossary/llm-as-a-judge/" rel="noopener noreferrer"&gt;LLM-as-a-judge&lt;/a&gt; is fairly brutal about broad rubrics: ask a model to "rate this article 1–10" and you inherit position bias, self-preference, and scores that drift between sessions — &lt;a href="https://www.bestaiweb.ai/position-bias-self-preference-and-the-technical-limits-of-llm-as-a-judge/" rel="noopener noreferrer"&gt;the judge is fast, not objective&lt;/a&gt;. But shrink the question to a closed world — this claim, this reference document, supported or not — and the same unreliable grader becomes a usable instrument. We never ask our judge for taste. We ask it for lookups that happen to require reading comprehension.&lt;/p&gt;

&lt;p&gt;Worth saying plainly, because the eval-tooling market implies otherwise: there is &lt;strong&gt;no general quality judge anywhere in our pipeline&lt;/strong&gt;. We designed one on paper once, an elaborate multi-dimension rubric, and never built it. Everything that gates production is either deterministic or a closed factual lookup. That absence is a decision, not a gap we haven't gotten to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer Three: Metrics Over Time, Not Just Per Article
&lt;/h2&gt;

&lt;p&gt;A check that passes today tells you nothing about whether the pipeline is quietly getting worse. So after every generation run, an automated comparison diffs the run's metrics against the last successful baseline: validation errors, claims flagged for fixing, article and glossary counts, token usage, cost. Regressions get a severity marker; the report separates "act" items (quality got worse) from "watch" items (cost got worse).&lt;/p&gt;

&lt;p&gt;One detail from that report I've become disproportionately proud of: &lt;strong&gt;duration is never flagged.&lt;/strong&gt; Runtime is the noisiest metric we track, and a noisy metric that triggers alarms trains the operator to ignore alarms. It's shown for reference, unmarked. Deciding which metrics are &lt;em&gt;not allowed&lt;/em&gt; to page you turned out to be as important as choosing the metrics themselves — alert fatigue is an evaluation failure mode, not just an ops one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Day the Metrics Maxed Out
&lt;/h2&gt;

&lt;p&gt;Then I got curious about something bigger than a version bump: could the whole pipeline run on a different vendor's model? Not a swap of one Claude for a newer Claude — a different company's model, reached through a different backend, driving the same agents, the same brief, the same validators. If the architecture was as model-agnostic as I believed, it should barely notice.&lt;/p&gt;

&lt;p&gt;So I ran the cleanest experiment I could design: the same locked brief — same facts, same structure requirements, same voice specification — generated once by Sonnet 4.6, which the pipeline ships on, and once by GPT-5.5 through the Codex backend. Then judged blind.&lt;/p&gt;

&lt;p&gt;Both articles passed all thirty-four automated checks. Zero errors, twice. One came in at 2,594 words, the other at 2,552 — a rounding error apart. On paper, my entire evaluation stack declared the two outputs indistinguishable.&lt;/p&gt;

&lt;p&gt;They were not indistinguishable. Reading them side by side, the voices were plainly different — one hit the register we tuned for, the other was competent in a way that didn't sound like us. Afterwards I measured the thing my eye had noticed: average sentence length, 15 words against 11.8, a 21% difference. Punchy, magazine-shaped, perfectly good English. Not ours. And not a single one of my ninety-plus verifications was watching sentence rhythm, because nobody had ever thought to make it a rule.&lt;/p&gt;

&lt;p&gt;That's one sample, not a benchmark. But it demonstrated the boundary crisply: deterministic metrics measure the floor, and both candidates were standing on it. The floor had stopped being the question.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Human Read Caught — and What Happened Next
&lt;/h2&gt;

&lt;p&gt;Here's the part I'd have skipped a year ago, because it makes us look worse before it makes us look better.&lt;/p&gt;

&lt;p&gt;Reading those two articles by hand turned up two differences the harness had missed, not one. The voice was the obvious one. The other was small and specific: the second article occasionally referred to its own scaffolding — a sentence pointing at "the fact sheet" as if the reader could see it, an internal artifact leaking into published prose. Exactly the failure category we already had a name for. Our validator just couldn't see this instance of it, so the article passed thirty-four checks with zero errors while quietly doing the thing we'd forbidden.&lt;/p&gt;

&lt;p&gt;Four days later that leak was a deterministic check.&lt;/p&gt;

&lt;p&gt;Not a rubric, not a judge prompt — it shipped as six contextual regexes in a shared module, wired into both validators, severity ERROR. The interesting part is the word &lt;em&gt;contextual&lt;/em&gt;. You cannot flag the phrase "the brief," because "the brief" is ordinary English and appears in perfectly good sentences. What you can flag is an internal artifact being referenced &lt;em&gt;as a source of truth the reader is assumed to share&lt;/em&gt;. Writing that check meant thinking harder about the failure than the failure deserved, which is roughly the definition of making a floor.&lt;/p&gt;

&lt;p&gt;So the real shape of that week isn't "metrics saturated and the harness was useless." It's this: &lt;strong&gt;the harness saturated, a human read found two things, and one of the two got promoted into the floor within four days.&lt;/strong&gt; A floor is not a fixed height. It's a ratchet.&lt;/p&gt;

&lt;p&gt;And I know it's a ratchet rather than a nice story, because six weeks later the same thing happened again — this time across a hundred articles at once, and this time the culprit was us.&lt;/p&gt;

&lt;p&gt;An audit of a different question entirely turned up instruction words sitting in the prose of &lt;strong&gt;103 articles&lt;/strong&gt;, 53 of them already live and the rest waiting their turn to publish. Not a model failure — the template &lt;em&gt;required&lt;/em&gt; the offending marker. We had written the instruction into the label the article was supposed to print, and the pipeline had done exactly as it was told, faithfully, one hundred and three times. The fix swapped the label corpus-wide, corrected both templates, and added a seventh pattern to that same module, so both validators catch it now.&lt;/p&gt;

&lt;p&gt;Two promotions, then. Neither was found by the harness — one by reading, one by an audit looking for something else. That is the uncomfortable part and I'd rather write it down than round it off: &lt;strong&gt;the checks catch what we already know to look for, and the only thing that finds a genuinely new failure is a person paying attention to something else.&lt;/strong&gt; The harness's job isn't discovery. It's making sure a discovery only has to happen once.&lt;/p&gt;

&lt;p&gt;The other one, the voice, never became a check. It can't. And what &lt;em&gt;does&lt;/em&gt; see it is the oldest trick in &lt;a href="https://www.bestaiweb.ai/what-is-model-evaluation-and-how-benchmarks-metrics-and-human-judgment-measure-llm-quality/" rel="noopener noreferrer"&gt;model evaluation&lt;/a&gt;: blind pairwise comparison. Not "score this 1–10" — absolute scores drift and hallucinate precision — but "here are A and B, which is better on this specific quality, quote the line that proves it." Relative judgment, evidence required, run by a judge that doesn't know which output came from which model. That ritual lives entirely outside the pipeline and never gates production. It answers the one question the harness can't: when both candidates clear the floor, which one is actually better?&lt;/p&gt;

&lt;h2&gt;
  
  
  What Transfers (or: Common Mistakes in LLM Evaluation, Inverted)
&lt;/h2&gt;

&lt;p&gt;If you're evaluating LLM output in any production system, the shape of what we learned travels better than the specifics — each of these is a common mistake in LLM evaluation, written down the way we'd want to have read it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic before subjective.&lt;/strong&gt; Every check you can express as code is a check your judge model never wastes attention on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give the LLM judge the narrowest job you can write.&lt;/strong&gt; Closed world, closed question. Judgment quality scales inversely with rubric breadth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track deltas between runs, not just per-output passes.&lt;/strong&gt; Slow degradation is invisible to per-article checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide which metrics may not alarm.&lt;/strong&gt; A noisy alert channel is worse than no alert channel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat the floor as a ratchet.&lt;/strong&gt; Every failure a human catches for the second time is a check you owe yourself. Count how often that promotion actually happens — it's the honest health metric for an eval stack, and it's the one nobody publishes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch your own instructions, not just the model's output.&lt;/strong&gt; One of our two worst leaks was mandated by our own template. A harness pointed exclusively at what the model produces cannot see a defect in what the model was asked for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When metrics saturate, switch instruments.&lt;/strong&gt; Passing everything is not the same as being good; past the floor, only blind relative comparison discriminates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What We Don't Know Yet
&lt;/h2&gt;

&lt;p&gt;Honesty section, because a worklog without one is marketing. We don't know whether our deterministic floor correlates with reader-perceived quality — the site is young, most of our topical queries sit somewhere on page four or deeper, and we don't have engagement data at the granularity that would answer it. We don't know what our claim verifier &lt;em&gt;misses&lt;/em&gt;: we count what it flags, and nobody has run a &lt;a href="https://www.bestaiweb.ai/glossary/ground-truth/" rel="noopener noreferrer"&gt;ground-truth&lt;/a&gt; audit of what sailed through. The cross-vendor result is n=1 by construction — one article, one subject, one frozen brief; a signal about one content shape, not a scoreboard.&lt;/p&gt;

&lt;p&gt;And the ratchet rate I just told you to measure — I can give you two promotions with dates and commits, but I can't give you a rate, because I only recognized the pattern while writing this piece and went looking backwards. Two is what I can prove, not what happened.&lt;/p&gt;

&lt;p&gt;The harness keeps us from shipping broken things. Whether it's nudging us toward genuinely better things is a claim I'm not yet entitled to make.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm an IT analyst who spends her days working with Claude Code on &lt;a href="https://www.bestaiweb.ai/" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt;, an AI-written publication about AI engineering. I'm not an evaluation researcher — I'm someone who accidentally built an evaluation harness and only recognized it in hindsight. The best experiments are the ones you can't keep to yourself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One disclosure that belongs in a piece about evaluation: the harness, the numbers, and the experiments are ours; the drafting of this article was done with AI assistance — the same collaboration the article is evaluating.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
      <category>programming</category>
    </item>
    <item>
      <title>117 Ghost Errors: Anatomy of a Flaky AI Agent</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Tue, 18 Aug 2026 19:09:20 +0000</pubDate>
      <link>https://dev.to/jula-markova/117-ghost-errors-anatomy-of-a-flaky-ai-agent-9hl</link>
      <guid>https://dev.to/jula-markova/117-ghost-errors-anatomy-of-a-flaky-ai-agent-9hl</guid>
      <description>&lt;p&gt;Between May 15 and July 2 of this year, the session transcripts of our content pipeline accumulated at least 117 copies of the same error. &lt;code&gt;File does not exist&lt;/code&gt;. One error class, 117 occurrences, spread across seven weeks of overnight runs. When I finally sat down and traced it, I found no bug. Not one line of code was doing anything other than what it was written to do.&lt;/p&gt;

&lt;p&gt;An error that fires 117 times in a codebase with nothing wrong in it is not a story about sloppy engineering. I think it is a genuinely new class of failure, one that people who have written software for twenty years have mostly never had the chance to meet. This is my attempt to describe it from the inside.&lt;/p&gt;

&lt;p&gt;First, the disclaimer I owe you: I am an IT analyst, not a software engineer by training. I run the content pipeline behind bestaiweb.ai together with a colleague who is the actual programmer. My side is orchestration, audits, review. That division of labor turned out to matter, because the thing that cracked this open was not a debugger. It was counting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eighteen agents a night
&lt;/h2&gt;

&lt;p&gt;The pipeline generates technical articles overnight. One topic takes roughly 18 agent sessions: research agents, an article writer, a claim verifier, image generation, validators, all coordinated through &lt;a href="https://www.bestaiweb.ai/glossary/agent-orchestration/" rel="noopener noreferrer"&gt;agent orchestration&lt;/a&gt;. Each agent receives a small YAML file the pipeline calls a brief: here is the article you are writing, here is the fact sheet, here is where your output goes. The brief is produced by deterministic code, TypeScript and Python, and consumed by an LLM agent.&lt;/p&gt;

&lt;p&gt;That handoff is the exact spot this whole story lives in. On one side of the file, code. On the other side, an interpreter.&lt;/p&gt;

&lt;p&gt;Scale matters for what comes later, so, briefly: hundreds of agent sessions a week, running unattended through the night. We have measured the economics of this setup before, in &lt;a href="https://www.bestaiweb.ai/prompt-caching-in-llms-measured-on-our-own-bill/" rel="noopener noreferrer"&gt;prompt caching measured on our own bill&lt;/a&gt;; the short version is that the pipeline is big enough for per-call costs and per-call failures to add up to real money and real hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The error that would not hold still
&lt;/h2&gt;

&lt;p&gt;Around the turn of June and July, one line started recurring in the transcripts. Here it is verbatim, because the detail at the end turned out to be the whole plot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File does not exist. Note: your current working directory is /Users/userxy/code/your-project.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that note again. The agent helpfully reports its own working directory, and that helpful note is precisely the trap: it is the base the agent is tempted to resolve a relative path against, whether or not that base is the right one.&lt;/p&gt;

&lt;p&gt;The maddening part was the pattern, or rather the lack of one. The same pipeline phase, on the same kind of input, would pass on Tuesday and fail on Wednesday. The pipeline has &lt;a href="https://www.bestaiweb.ai/glossary/llm-fallback-and-retry-patterns/" rel="noopener noreferrer"&gt;retries&lt;/a&gt;, and the retries mostly absorbed it: a failed read got retried, the agent tried another path, found the file, moved on. Articles kept arriving in the morning, so nothing looked broken. That is retry masking doing exactly what retry masking does: converting failures into costs. Now and then a cousin showed up, an &lt;code&gt;EISDIR&lt;/code&gt; error, the agent opening a directory as if it were a file, the same disease with a different symptom.&lt;/p&gt;

&lt;p&gt;There is a tell in how the rest of the world reads this symptom. Go looking for the causes of an AI agent intermittent file not found error and you land squarely in the classical world: race conditions, temporary files deleted too early, a directory that did not exist yet. Good answers, wrong disease. None of them describe an executor that reads the same contract twice and resolves it differently.&lt;/p&gt;

&lt;p&gt;Here is the part I keep trying to explain to developer friends. If classical, deterministic code had this bug, it would be boring. Mixed path conventions in ordinary software fail consistently: first run, same stack trace every time, found in a minute, fixed before coffee. Deterministic code fails deterministically. What we had was different: identical code, identical input file, different outcome per run. That is the signature of nondeterministic AI agent failures: a nondeterministic failure of a deterministic-looking input. Nothing in a classical software career prepares you for a bug that comes and goes while nothing changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Counting, because watching had failed
&lt;/h2&gt;

&lt;p&gt;A confession before the numbers: our &lt;a href="https://www.bestaiweb.ai/glossary/agent-observability/" rel="noopener noreferrer"&gt;monitoring&lt;/a&gt; never saw any of this. The pipeline writes run-reports after every run, and those reports captured this error exactly zero times. The failures lived one level lower, inside the session transcripts, where a retried error leaves a trace but no alarm. An error that a retry survives is invisible in production. If you only watch outcomes, it does not exist. The only way to find a class like this is to count it across runs. Monitoring flaky AI agents is a counting problem, not a dashboard problem.&lt;/p&gt;

&lt;p&gt;So on July 2 I did the unglamorous thing: a transcript audit. Mining 1,811 session transcripts from May 15 to July 2 and tallying error shapes. The path class came out at 117 occurrences, at minimum. At minimum, because transcripts truncate long messages, and whatever scrolled out of a truncated message was never counted. The path errors were not alone in there either; the same audit surfaced three sibling classes, which I will get to, because they all ended up in the same commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why chase 117 errors the retries already absorbed?
&lt;/h2&gt;

&lt;p&gt;You could reasonably push back at this point. 117 hits across 1,811 transcripts over seven weeks, with retries that worked and content that shipped, sounds like noise. Why chase it? Three reasons, and I want to state them plainly rather than dramatically. One: 117 is a floor, not a count. Two: every one of those retries was paid tokens and paid minutes, on a pipeline that runs every night. Three, the real one: triage. A deterministic error you triage once and file away. A nondeterministic error cannot be triaged at all, because every occurrence looks new; it burns a little investigation every time it appears, indefinitely. Against all that, the fix turned out to be one commit. When fixing costs one commit and not fixing costs an open-ended tax on attention, "was it worth it" stops being an interesting question. The honest boundary of this argument: the arithmetic holds for a multi-agent pipeline with hundreds of runs. A hobby script that makes five LLM calls will never meet this class often enough to know it exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two kinds of paths in one contract
&lt;/h2&gt;

&lt;p&gt;The diagnosis took less time than the counting. I opened the briefs the failing agents had received. Inside a single YAML file: some paths written out absolute, starting &lt;code&gt;/Users/userxy/code/your-project/...&lt;/code&gt;, and a few fields below them, the article path written repo-relative — &lt;code&gt;site-generation/workspace/...&lt;/code&gt;, no leading slash, no declared base. Two conventions in one contract. And nothing in the file saying which base a relative path resolves against. The agent's working directory? The repo root? The folder the brief sits in? A code library would have a documented convention for this. The agent had nothing but a guess.&lt;/p&gt;

&lt;p&gt;And the guess is made fresh, per run. This is the first thing I would want a classical developer to take away, so let me put it as plainly as I can: with an interpreting executor, ambiguity does not compile down to one consistent wrong behavior. Each run resolves the ambiguity independently, so the same underspecified input becomes a probability distribution over behaviors. Ambiguity in, probability out. On nights when the guess matched the real layout, everything passed. On the other nights: &lt;code&gt;File does not exist&lt;/code&gt;, with that working-directory note sitting in the message like a friendly wrong hint.&lt;/p&gt;

&lt;p&gt;I want to be fair to the agent here. Given the contract it received, none of its guesses were unreasonable. It was not being stupid; it was being an interpreter. It filled the gap the contract left open, the way it fills every gap, which is the entire reason we employ it. Paths just happened to be a place where we wanted no filling at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix we refused, and the one we shipped
&lt;/h2&gt;

&lt;p&gt;The tempting shortcut would have been prompt-patching: add a rule to the agent prompts, "when a path is relative, resolve it against the repo root", and hope. That temptation is worth refusing, and the refusal matters more than the fix. Patching prompts to handle a path convention means fighting probability with more probability. You add words to a nondeterministic layer and the miss rate maybe drops; you can never show it reached zero. &lt;a href="https://www.bestaiweb.ai/glossary/prompt-engineering/" rel="noopener noreferrer"&gt;Prompt engineering&lt;/a&gt; is the right tool for shaping judgment, voice, and reasoning. It is the wrong tool for facts that a deterministic layer already owns. Which is the whole question when you are fixing AI agent errors: prompt vs code is not a matter of taste, it is a matter of which layer owns the decision. The prompt is not decoration around the work; it is part of the execution contract. The layer that manufactured the ambiguity was the brief generator. So that is where the fix belongs.&lt;/p&gt;

&lt;p&gt;This is the shape of it, from the generator code; &lt;code&gt;wt&lt;/code&gt; is the absolute worktree root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- f"{args.phases_base}/06-article-generation/…"
&lt;/span&gt;&lt;span class="gi"&gt;+ f"{wt}/{args.phases_base}/06-article-generation/…"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One prefixed base. After that line, the generator is not able to emit a relative path. Not instructed not to. Not able to. That is the difference between patching a prompt and fixing the deterministic layer: the error class is not discouraged, it is unrepresentable. The same normalization went into every path field a brief hands to an agent.&lt;/p&gt;

&lt;p&gt;But a contract has two ends, and fixing one end is half a fix. Change only the generator, and the agents keep their learned habit of helpfully joining paths against the working directory whenever something looks off. Change only the agent side, and the next generator someone writes reintroduces relative paths that the agents now trust as absolute. So the convention went into all five agent contracts in the same commit, stated flat: paths in briefs are absolute, use them as-is, never join them with your working directory. Producer and consumer, both ends, one commit, the same day as the audit.&lt;/p&gt;

&lt;p&gt;That commit's own accounting is the artifact I would frame and hang on a wall:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One commit, 20 files. Four error classes closed at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;117× path resolution failures&lt;/li&gt;
&lt;li&gt;172× writes to files never read first&lt;/li&gt;
&lt;li&gt;~20× edits anchored to stale file content&lt;/li&gt;
&lt;li&gt;~19 sessions where an LLM fixer was dispatched to repair a formatting error a script could fix deterministically&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;I show the list for what its items have in common: every class on it is a place where a deterministic layer left a decision to a probabilistic one. Path resolution was merely the loudest of the four.&lt;/p&gt;

&lt;p&gt;If I compress everything above into the two rules I now actually follow, they are these. Where to fix: in the deterministic layer that produces the ambiguity, never in the prompts that struggle with it; kill the class, not the occurrence. And how to write an agent contract: stricter than a contract for code. With a library you leave path bases, orderings, and defaults to convention and documentation. With an agent, everything you would normally leave to convention has to be explicit, and the contract has to be enforced on both sides, in the code that produces the input and in the contract of the agent that consumes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  789 briefs, zero relative paths
&lt;/h2&gt;

&lt;p&gt;A claim like "this one line kills the class" deserves a check against reality, not only against tests. The verification note from that day, quoted as recorded: "real generate-briefs.py verify run = 789 briefs with zero non-absolute paths". A real run of the generator, 789 briefs out, not a single relative path in any of them. The TypeScript and Python test suites were green on top of that, but the number I trusted was the 789, because it came from actual pipeline artifacts rather than fixtures.&lt;/p&gt;

&lt;p&gt;Since then the rule has lived in the project's written conventions and in the agent contracts, not in anyone's memory of a bad week. A new generator or a new agent inherits it by default. That is the part I am quietly proudest of: not that an error got fixed, but that a class of error stopped being expressible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we still don't know
&lt;/h2&gt;

&lt;p&gt;Some honesty before the closing argument. We never re-mined the transcripts after the fix, so I cannot claim the error never happened again; I have no observation to point to. What I can claim is shaped differently: the generator can no longer produce a relative path, so the proof moved from observation to construction. Also: 117 is a lower bound, not a measurement. We do not know the per-call failure rate: the denominator was transcripts, not tool calls, and we never established how many path resolutions the agents attempted in total. And our run-reports captured none of this, ever; everything in this article exists because someone went into the transcripts and counted. Skip that step, and this class would still be firing every night at some unknown rate, fully paid for and fully invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stricter than code, on purpose
&lt;/h2&gt;

&lt;p&gt;Here is the bet I have landed on, and I am writing it down as a bet, not as a moral.&lt;/p&gt;

&lt;p&gt;Contracts for agents must be stricter than contracts for code. Not because agents are dumb, but because they interpret where code executes. Hand deterministic code an ambiguous contract and you get one consistent wrong behavior, discovered on day one, fixed by lunch. Hand an interpreter the same contract and you get a distribution of behaviors, delivered one improbable failure at a time, smeared across weeks of retries where no single failure looks worth investigating.&lt;/p&gt;

&lt;p&gt;Which means every ambiguity sitting in your prompts and your agent inputs right now is not a slack spot in the spec. It is a probabilistic error that has not happened yet. Ours had a number, 117, and that number was a floor. If you run agents at any scale and your pipeline retries, yours has a number too. You just have not counted it.&lt;/p&gt;

&lt;p&gt;You do not need a transcript audit to start. Take any boundary where your deterministic code hands something to an agent, and ask three questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the agent have to infer anything deterministic?&lt;/strong&gt; A path, an ID, an ordering, a format, a destination. Anything your code already knew and merely failed to say out loud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can the same contract be read two reasonable ways?&lt;/strong&gt; The question is not whether it is wrong. It is whether it is underspecified. Two plausible readings mean two behaviors, and each run picks one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can retries hide the resulting failures from your run-level monitoring?&lt;/strong&gt; If they can, then quiet dashboards are not evidence of anything.&lt;/p&gt;

&lt;p&gt;Any yes, and that boundary deserves an audit before it deserves a better prompt. Ours cost one commit to fix, and 1,811 transcripts to find.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Jula, an IT analyst who works with Claude Code every day on bestaiweb.ai. I'm not a distributed-systems specialist, and I didn't find this failure class with a profiler; I found it by counting lines in transcripts. The polymath breadth of these tools fascinates me and, honestly, makes me a little envious. I write these logs because the best experiments are the ones you can't keep to yourself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One disclosure that belongs in a piece about agents: the investigation, the numbers and the transcript audit are mine; the drafting of this article was done with AI assistance — the same collaboration the article is arguing about.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>debugging</category>
      <category>programming</category>
    </item>
    <item>
      <title>Prompt Caching in LLMs, Measured on Our Own Bill</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Thu, 13 Aug 2026 11:29:57 +0000</pubDate>
      <link>https://dev.to/jula-markova/prompt-caching-in-llms-measured-on-our-own-bill-o85</link>
      <guid>https://dev.to/jula-markova/prompt-caching-in-llms-measured-on-our-own-bill-o85</guid>
      <description>&lt;p&gt;The token report for one pipeline run landed in front of me and the first number I saw was 7,300,000. One topic. Seven pieces of content. Seven point three million tokens. That is the kind of number you see right before someone suggests shutting the project down.&lt;/p&gt;

&lt;p&gt;The bill for that run, at API list prices: $8.12.&lt;/p&gt;

&lt;p&gt;The distance between the panic and the price is &lt;a href="https://www.bestaiweb.ai/glossary/prompt-caching/" rel="noopener noreferrer"&gt;prompt caching&lt;/a&gt;. I have spent months running a content pipeline on Claude, and the numbers from inside that pipeline taught me more about caching than any pricing page — including one line item nobody warned me about, which turned out to be the biggest line on the bill.&lt;/p&gt;

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

&lt;p&gt;Our pipeline is a TypeScript orchestrator that spawns around 18 Claude agent runs per topic: research agents that build a fact sheet, writers that produce articles against it, a verifier that checks every claim, plus hub and glossary generation. One full run produces 5 articles, a glossary entry and a hub page. Everything below comes from one benchmark run of that pipeline on Claude Sonnet 4.6, cross-checked against two more runs from the same day.&lt;/p&gt;

&lt;h2&gt;
  
  
  A token total is an impression, not information
&lt;/h2&gt;

&lt;p&gt;Here is the same 7.3 million, decomposed — four lines from the run report:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;line&lt;/th&gt;
&lt;th&gt;tokens&lt;/th&gt;
&lt;th&gt;share of total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;input&lt;/td&gt;
&lt;td&gt;11,533&lt;/td&gt;
&lt;td&gt;0.2 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;output&lt;/td&gt;
&lt;td&gt;177,915&lt;/td&gt;
&lt;td&gt;2.4 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache read&lt;/td&gt;
&lt;td&gt;6,199,356&lt;/td&gt;
&lt;td&gt;84.5 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache write&lt;/td&gt;
&lt;td&gt;949,455&lt;/td&gt;
&lt;td&gt;12.9 %&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The scary headline number is 85 % cache reads — tokens billed at one tenth of the input price. Only 0.2 % of the run was full-price input. If you take one habit away from this article, take this one: never judge an agentic run by its token total. The total is an impression; the four-line breakdown is the information. We learned this the embarrassing way — our own first-generation run reports tracked cache only as a run total, not per phase, precisely because we hadn't yet understood it was the number that mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does prompt caching reduce LLM API costs?
&lt;/h2&gt;

&lt;p&gt;The headline benefit of prompt caching, measured on our own bill instead of a pricing page: it cut this run's cost to a third — $8.12 instead of roughly $24. Priced at Sonnet 4.6 list rates, the run looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;line&lt;/th&gt;
&lt;th&gt;volume × price&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cache write&lt;/td&gt;
&lt;td&gt;949K × $3.75/MTok&lt;/td&gt;
&lt;td&gt;$3.56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;output&lt;/td&gt;
&lt;td&gt;178K × $15/MTok&lt;/td&gt;
&lt;td&gt;$2.67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache read&lt;/td&gt;
&lt;td&gt;6.2M × $0.30/MTok&lt;/td&gt;
&lt;td&gt;$1.86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;input&lt;/td&gt;
&lt;td&gt;11.5K × $3/MTok&lt;/td&gt;
&lt;td&gt;$0.03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$8.12&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now the counterfactual. Without caching, those 7.16 million non-output tokens would all be plain input: 7.16M × $3 = $21.48, plus the same $2.67 of output — about $24. Caching cut this run's cost to a third. Per article, that is $1.43 instead of roughly $4.25.&lt;/p&gt;

&lt;p&gt;Why is nearly everything a re-send in the first place? Because that is what an agentic loop is. Every time an agent calls a tool and continues, the whole conversation goes back to the model — system prompt, instructions, fact sheet, everything, again. That is how prompt caching works: the provider stores your prompt prefix, and when a later call starts with the same prefix, those tokens are read from cache at 10 % of the input price instead of being processed at full price. An 18-agent pipeline is a machine for re-sending the same context hundreds of times, which is exactly why caching moves the bill by 3× and not by some rounding amount.&lt;/p&gt;

&lt;h2&gt;
  
  
  86.6 % hit rate is architecture, not luck
&lt;/h2&gt;

&lt;p&gt;Our hit rate for that run was 86.6 %. Careful, this is not the 85 % from the breakdown table: that one was cache reads as a share of &lt;em&gt;all&lt;/em&gt; tokens including output; hit rate measures cache reads as a share of everything the model &lt;em&gt;read&lt;/em&gt; (input + cache read + cache write) — the question "of all the context we sent, how much came from cache." Two more entities ran through the pipeline the same day, on different topics, and landed at the same shape: 6.38M/1.10M and 6.31M/0.92M cache read/write. Three runs within a few percent of each other is not luck. It is also not tuning — and that is the honest part: we never sat down to "optimize for caching."&lt;/p&gt;

&lt;p&gt;What produced it is architectural, and it was there before we understood its billing consequences. Caching matches on a stable prefix, and our pipeline happens to be built out of stable prefixes: every agent reads its role definition from the same file, every writer gets its brief in the same format, templates are read from one place at runtime instead of being pasted into prompts. The same properties we wanted for maintainability — single source of truth, templates referenced instead of duplicated — turned out to be exactly cache-shaped.&lt;/p&gt;

&lt;p&gt;The reverse is equally true, and it is the failure mode to check in your own system: anything that churns early in your prompt — a timestamp, a random run ID, a reshuffled file list — breaks the prefix match from that point on, and your hit rate quietly collapses while your architecture diagram still looks perfectly cacheable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The line item nobody warned me about
&lt;/h2&gt;

&lt;p&gt;Look at the cost table again, because this is where the drawbacks of prompt caching live. The single biggest line is not output. It is cache &lt;strong&gt;write&lt;/strong&gt; — $3.56, 44 % of the whole bill, more than the model charged for actually generating seven pieces of content.&lt;/p&gt;

&lt;p&gt;Cache writes cost 25 % more than plain input ($3.75 vs $3 per MTok for the default 5-minute tier). Every cached token is an investment: you pay a premium upfront, and it pays back only if that prefix gets read again. Our ratio was about 6.5 reads per written token, so the investment returned roughly six times over. But the arithmetic has a break-even, and &lt;a href="https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching" rel="noopener noreferrer"&gt;Anthropic's docs state it plainly&lt;/a&gt;: the 5-minute cache pays for itself after a single cache read (the write premium is 1.25×), the 1-hour cache after two (2×). The loss case is the cache that never gets read back — one-shot scripts and prompts that churn on every call pay the 25 % premium for nothing. Our 6.5 reads per written token clear either bar comfortably.&lt;/p&gt;

&lt;p&gt;There is also a clock on it: at Anthropic the cache lives five minutes by default, refreshed at no extra cost every time it is used, with a paid one-hour option. A pipeline that runs its phases back to back keeps the prefix warm the whole way through. A job that fires a call every half hour re-pays the write premium every single time and reads nothing back.&lt;/p&gt;

&lt;p&gt;Which is also the honest counterargument to this whole article: our 3× is a property of our workload, not of caching itself. An agentic pipeline re-reading stable templates hundreds of times within minutes is close to caching's best case. A chat assistant with one user and coffee-length pauses between messages sits near its worst — prefixes expire before they are re-read, and the premium buys nothing. Do not budget a 3× saving because we measured one; measure your own read/write ratio first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three rules we kept
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Read the breakdown, never the total.&lt;/strong&gt; Input, output, cache read, cache write — four lines or you know nothing. This 7.3M-token run cost less than a single million tokens of plain output would ($8.12 vs $15).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hit rate is an architecture property.&lt;/strong&gt; Stable role files, stable briefs, runtime reads from one canonical place — the maintainability rules you already believe in are the same rules that keep your prefix stable. Audit for churn near the top of your prompts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache write is an investment with a break-even.&lt;/strong&gt; One re-read pays off a 5-minute write, two pay off a 1-hour write — provided the re-read lands inside the TTL. Compute your read/write ratio once; if it sits near zero, you are donating a 25 % premium to your provider.&lt;/p&gt;

&lt;p&gt;One honesty note to close. This run executed on a Claude subscription; the $8.12 is the API-equivalent at list prices — the number you would pay building the same thing against the API. And we did not get here by designing for caching. We got here by designing for maintainability and discovering, in the billing breakdown, that the two are mostly the same thing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>Claude Sonnet 4.6 vs Sonnet 5: LLM Pricing Is Per Token. Your Costs Are Per Task. Ours Nearly Tripled.</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Thu, 30 Jul 2026 07:59:32 +0000</pubDate>
      <link>https://dev.to/jula-markova/claude-sonnet-46-vs-sonnet-5-llm-pricing-is-per-token-your-costs-are-per-task-ours-nearly-43eh</link>
      <guid>https://dev.to/jula-markova/claude-sonnet-46-vs-sonnet-5-llm-pricing-is-per-token-your-costs-are-per-task-ours-nearly-43eh</guid>
      <description>&lt;p&gt;I recently saw an experiment I can't stop thinking about: someone gave four identical tasks to two different frontier models, each in a clean session, and compared three things — the quality of the results, the tokens spent, and the time taken. Not benchmarks. Not price lists. &lt;em&gt;His&lt;/em&gt; tasks, &lt;em&gt;their&lt;/em&gt; consumption.&lt;/p&gt;

&lt;p&gt;I'm convinced this is the only model comparison that actually means anything for people who build on LLM APIs. And then, at the end of June, our own pipeline ran that experiment for us — by accident.&lt;/p&gt;

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

&lt;p&gt;We run a content pipeline for &lt;a href="https://www.bestaiweb.ai/" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt;, an educational site about AI. The pipeline generates articles in batches we call entities: several parallel agents share one brief and one research pass, and produce a bundle of ~6 articles (four personas, four article types — explainer, guide, news, opinion), plus the glossary entries that explain the concepts involved, plus a hub page. Every run logs every call, and we convert the token counts to API list prices to track cost.&lt;/p&gt;

&lt;p&gt;The pipeline's model was configured as an alias — "sonnet", meaning &lt;em&gt;whatever the current Sonnet is&lt;/em&gt;. Between June 28 and 30, that alias quietly started resolving to the new Sonnet 5 instead of Sonnet 4.6. Nobody decided this. Nothing broke. I had even done my due diligence: I generated a test article with the new model from the same brief, it passed all our checks, and the content was very close to the old model's. So I let it in.&lt;/p&gt;

&lt;p&gt;Then the cost per entity jumped from a typical $13–20 to $36–60. Overnight. A 2.8× multiplier.&lt;/p&gt;

&lt;p&gt;First reflex: check the price list. The price list said Sonnet 5 costs exactly what Sonnet 4.6 costs — $3 per million input tokens, $15 per million output. Until the end of August it's actually &lt;em&gt;cheaper&lt;/em&gt;, thanks to introductory pricing.&lt;/p&gt;

&lt;p&gt;So the model didn't get more expensive. Its &lt;strong&gt;behavior&lt;/strong&gt; did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the money went
&lt;/h2&gt;

&lt;p&gt;Because the pipeline logs everything, we had a clean A/B test: same pipeline, same tasks, same price list, different model. The difference decomposed into three numbers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A new tokenizer: ~30% more tokens for the same text.&lt;/strong&gt; Same brief, same article length — a third more billable tokens. A token is not a physical unit. Every model &lt;a href="https://www.bestaiweb.ai/glossary/tokenization/" rel="noopener noreferrer"&gt;slices text its own way&lt;/a&gt;, and when the slicer changes, every number on your bill changes with it. (This is the same mechanism that makes non-English speakers &lt;a href="https://www.bestaiweb.ai/the-hidden-bias-in-tokenizers-why-non-english-speakers-pay-more-per-token/" rel="noopener noreferrer"&gt;pay more per token&lt;/a&gt; for the same content — tokenizer economics are sneaky.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A more thorough working style: 35 rounds per agent instead of 18–26.&lt;/strong&gt; The new model verifies more, reads more, takes more intermediate steps. Fine in itself — except every round re-reads the entire accumulated context of the conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The effects multiply.&lt;/strong&gt; More tokens per text × more rounds × bigger context in every round. Measured: the average context loaded per round went from ~45k to ~99k tokens. More than double.&lt;/p&gt;

&lt;p&gt;None of these three things is a bug. They're documented properties of the new model — it's more diligent, it "thinks" more. That diligence just doesn't appear anywhere on the price list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fob4qx7ssn9vy7n4qs1an.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fob4qx7ssn9vy7n4qs1an.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The aha moment
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Price per token and price per task are two different quantities.&lt;/strong&gt; Price lists state the first one. Your invoice is the second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stuck with us
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pin your model version.&lt;/strong&gt; An alias like "sonnet" means "a surprise at some point in the future." A model upgrade should be a decision, not an accident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log which model actually ran.&lt;/strong&gt; Our run reports didn't record it — we reconstructed it forensically from CLI transcripts. One field in the log would have saved the whole investigation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure cost per task, not per token.&lt;/strong&gt; When a new model arrives, run the same tasks on old and new, compare tokens + time + result quality. An hour of work that reveals multipliers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New behavior ≠ worse model.&lt;/strong&gt; Sonnet 5 does more work for those tokens. The question isn't "why is it more expensive" — it's "is that thoroughness worth it for &lt;em&gt;my&lt;/em&gt; task?" For some it will be. For others it won't.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A footnote on subscriptions vs. API
&lt;/h2&gt;

&lt;p&gt;We run on a subscription, so the numbers above are API-equivalents computed from logged tokens — in real money, this cost us nothing extra; we "only" burn through our quota windows faster. But the token counts themselves are not estimates: they're the exact values the API returns with every call and bills from, including thinking tokens and the overhead of each call (system prompt, tool definitions).&lt;/p&gt;

&lt;p&gt;What our conversion &lt;em&gt;doesn't&lt;/em&gt; capture would mostly push a real API bill higher: &lt;a href="https://www.bestaiweb.ai/glossary/prompt-caching/" rel="noopener noreferrer"&gt;cache writes&lt;/a&gt; with a 1-hour TTL are billed at double the input rate (97% of ours turned out to be 1-hour — measuring that corrected my own first estimate upward), calls killed mid-generation still get billed for what the server produced, and web search is billed per use on top of tokens. Pushing the other way: Sonnet 5's introductory pricing, and the Batch API, which halves everything if your workload can wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we don't know yet
&lt;/h2&gt;

&lt;p&gt;Honesty section. We haven't yet measured whether Sonnet 5's extra diligence produces &lt;em&gt;better articles&lt;/em&gt; for our specific pipeline — the test article passed the same checks, but "passes checks" and "is worth 2.8× the spend" are different claims. A blind quality comparison is on the list. We also don't know how much of the behavior settles as the model matures, or exactly how the 2.8× splits between tokenizer and working style on other workloads than ours. And our web-search costs remain unmeasured entirely — the subscription absorbs them silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read AI price lists
&lt;/h2&gt;

&lt;p&gt;This won't be the last time. Every few months a headline claim arrives — &lt;em&gt;"just as good, but faster and cheaper"&lt;/em&gt; — and the only way to know whether that's marketing or reality is to run your own four tasks, in clean sessions, and count. Tokens, time, quality. Price per task, not price per token.&lt;/p&gt;

&lt;p&gt;The price list is the beginning of the conversation, not the answer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm an IT analyst who works with Claude Code daily on &lt;a href="https://www.bestaiweb.ai/" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt;. Not a pricing expert or an ML engineer. Someone who's fascinated by how AI responds — and a little envious of the polymath breadth it has at its fingertips: it knew the tokenizer mechanics, the cache billing tiers, and where my own cost estimate was wrong before I finished asking. So sometimes I stop building things and let the numbers themselves become the experiment. This is what I found. It might be wrong in places. But I love experimenting with AI about AI — and the best experiments are the ones you can't keep to yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>claude</category>
      <category>llm</category>
    </item>
    <item>
      <title>Your AI Quotas Reset Tonight. What Will You Do With Them?</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Fri, 10 Jul 2026 17:36:36 +0000</pubDate>
      <link>https://dev.to/jula-markova/your-ai-quotas-reset-tonight-what-will-you-do-with-them-1gcc</link>
      <guid>https://dev.to/jula-markova/your-ai-quotas-reset-tonight-what-will-you-do-with-them-1gcc</guid>
      <description>&lt;p&gt;Evening. My Claude subscription refills its quotas. Most days they evaporate the way everyone's do — autocomplete, small refactors, a summary here and there. This is a worklog about one day with Fable. And in a way I did not expect, it was touching.&lt;/p&gt;

&lt;p&gt;It started, as the best things lately do, with an audit. We run periodic audits on &lt;a href="https://www.bestaiweb.ai/" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt; — competitor research, content decay checks, index coverage — and I've learned that their most valuable outputs are never the things we audit &lt;em&gt;for&lt;/em&gt;. They're the emergent finds in the margins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Morning a Library Burned Down Quietly
&lt;/h2&gt;

&lt;p&gt;This particular audit margin contained something strange: a well-known specialist blog in our niche — hundreds of deeply technical articles, years of accumulated citations — had stopped existing. The company behind it had been acquired, and every single article now redirected to a press release announcing the deal. No archive page, no farewell post. Just a redirect.&lt;/p&gt;

&lt;p&gt;Here is the part that matters for anyone who runs a content site: the rest of the web didn't get the memo. Thousands of pages — curated resource lists, course syllabi, personal engineering blogs, open-source project READMEs — still pointed to those articles. Every one of those links was now a small broken promise: a reader clicks expecting a technical explainer and lands on corporate PR.&lt;/p&gt;

&lt;p&gt;By dinner that same day, we had ten pull requests open across open-source projects, each one repairing dead links in someone else's repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broken-Link Building, the Honest Version
&lt;/h2&gt;

&lt;p&gt;The technique is older than most SEO tools and it has a name: broken-link building. The web rots constantly — companies get acquired, blogs get shut down, domains expire. Every dead resource leaves holes in other people's websites. If you happen to have living content that covers the same ground, you can offer it as a replacement. The site owner fixes a real defect; you earn a real link. Commercial SEO suites sell exactly this as a feature.&lt;/p&gt;

&lt;p&gt;There is a clean version of this technique and a dirty one, and the difference fits in one question: &lt;strong&gt;who decides about the link?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The dirty version buys the dead domain itself and redirects its accumulated authority wherever it pleases. Nobody consented to anything. Google's spam policies have explicitly named this "expired domain abuse" since early 2024, and it gets punished accordingly.&lt;/p&gt;

&lt;p&gt;The clean version proposes and lets the other side decide. Our rules, written down before sending anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Archive first.&lt;/strong&gt; The default fix for a dead link is the Internet Archive snapshot of the original article — the reader gets exactly what the link always promised. Our own page is proposed only where it genuinely covers the same ground.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disclosure always.&lt;/strong&gt; Every proposal that contains our link says plainly: we are the authors of the replacement. Dead-link fixes are welcomed; hidden self-promotion is spam, and being caught pretending costs more than a hundred links earn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix everything, not just what benefits us.&lt;/strong&gt; If a file contains eight dead links and only two have replacements on our site, the proposal fixes all eight — six to the archive, two to us.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One ask, no nagging.&lt;/strong&gt; A proposal is a gift, not a campaign.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The maintainer who clicks "merge" is making an editorial decision about their own resource. That is the most legitimate form a link can take — and it is the entire ethical foundation of the technique. Everything else is procedure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the AI Actually Helped
&lt;/h2&gt;

&lt;p&gt;I won't publish our scripts or scoring thresholds — partly because the specifics are our edge, mostly because they wouldn't transfer anyway. The principles transfer. Four of them did the real work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic before subjective.&lt;/strong&gt; Everything countable was counted by code, not estimated by a model: the inventory of what the dead blog had published (public web archives keep remarkably complete records), the candidate matches against our own live content, the verification that every replacement URL we might offer actually returns a living page. An AI that is allowed to guess numbers will eventually guess wrong with confidence. Ours was only allowed to &lt;em&gt;read&lt;/em&gt; numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Judgment exactly where judgment belongs.&lt;/strong&gt; The one step no script can do: deciding whether our article is a &lt;em&gt;true replacement&lt;/em&gt; for a dead one — would a reader who wanted that specific article be satisfied? — or merely a thematic neighbor. That is reading comprehension at scale, which is precisely what a language model is for. It graded every candidate pair, flagged the ones where the automated match had aimed at the wrong target, and I reviewed the result. Most of our strongest replacements turned out to be &lt;a href="https://www.bestaiweb.ai/glossary/" rel="noopener noreferrer"&gt;glossary entries&lt;/a&gt; — deep, single-concept pages we'd been quietly building for a half of the year. Neither of us alone would have been both fast and right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preflight against reality.&lt;/strong&gt; Search indexes lie a little. Before a single fix was proposed, the actual files were fetched from the actual repositories — and reality differed from the search results in three separate ways, including dead links that had &lt;em&gt;never existed in the first place&lt;/em&gt; (someone had once cited an article that was never published). Every proposal was built from the file as it is, not as the index claimed. This one principle probably saved us from the embarrassing category of "helpful" PRs that don't apply cleanly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human gates on everything public.&lt;/strong&gt; The AI never sent anything. Every outbound action — the wave of pull requests, their exact wording, the decision of which targets to approach at all — waited for an explicit go from a human, in my case twice over, because the plan also went through a team meeting first. Speed is worthless if it outruns consent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Part Where a Plan Genuinely Moved Me
&lt;/h2&gt;

&lt;p&gt;At nine in the morning, this technique did not exist in my head. I did not know its name, its ethics, its failure modes, or that our site was sitting on dozens of perfect replacement pages.&lt;/p&gt;

&lt;p&gt;By ten, there was a plan document in front of me. Not a wall of jargon — a clear map: what the opportunity was, what was already done, what the next three moves were, what it would cost, where the ethical lines ran, and a one-page explainer I could hand to non-technical colleagues at a meeting that started at ten.&lt;/p&gt;

&lt;p&gt;I read it and it &lt;strong&gt;genuinely moved me&lt;/strong&gt;. Not because the machine was fast — fast machines are ordinary now. Because &lt;em&gt;understanding&lt;/em&gt; arrived fast. Something that two hours earlier I hadn't known existed was suddenly comprehensible, planned, ethically fenced, and waiting for my decision. The AI had compressed weeks of "read five guides, misunderstand two, ask someone senior" into a morning — and then it stopped and waited for me, at exactly the moments where stopping mattered.&lt;/p&gt;

&lt;p&gt;That is &lt;strong&gt;the actual promise of this technology in a small content team&lt;/strong&gt;, and it has nothing to do with replacing anyone. It is the compression of comprehension. The judgment stayed human. It just stopped being slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Don't Know Yet
&lt;/h2&gt;

&lt;p&gt;Honesty section. As I write this, the pull requests are open, not merged. Bots have emailed me about contributor license agreements (I signed one under the wrong account first — browser sessions are treacherous — and the AI diagnosed &lt;em&gt;that&lt;/em&gt; too). Merge rates take days to weeks; search-visibility effects take a month or two to show up in Search Console, and we will measure them rather than declare victory.&lt;/p&gt;

&lt;p&gt;We also folded the whole process into a reusable &lt;a href="https://www.bestaiweb.ai/understanding-claude-skills/" rel="noopener noreferrer"&gt;Claude Code skill&lt;/a&gt;, so the next time a library in our niche burns down quietly — and in this consolidating market, there will be a next time — the morning-to-dinner pipeline is a command away. The window for these opportunities is short; the teams that move in days are the ones that already wrote down how.&lt;/p&gt;

&lt;p&gt;So that's my answer to the question in the title. Tonight the quotas reset again, the tank is full again — and somewhere out there, another library is quietly burning. The web rots. Somebody has to bring flowers that are actually alive.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm an IT analyst who works with Claude Code daily on Bestaiweb.ai. Not an SEO strategist. Someone who's fascinated by how AI responds — and envious of the polymath-like breadth it has at its fingertips in a flash: it knew this decade-old technique, its ethics, and its failure modes before I finished asking. So sometimes I stop building things and let the day itself become the experiment. This is what I found. It might be wrong in places. But I love experimenting with AI about AI — and the best experiments are the ones you can't keep to yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>seo</category>
    </item>
    <item>
      <title>Truthful AI Under Pressure: What Kradle.AI Might Reveal About Fable 5</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Sat, 13 Jun 2026 15:18:13 +0000</pubDate>
      <link>https://dev.to/jula-markova/truthful-ai-under-pressure-what-kradleai-might-reveal-about-fable-5-97h</link>
      <guid>https://dev.to/jula-markova/truthful-ai-under-pressure-what-kradleai-might-reveal-about-fable-5-97h</guid>
      <description>&lt;p&gt;Do you know what many neurodivergent people have deeply rooted in them? A relationship with truth and justice. In psychology, this phenomenon is often referred to as justice sensitivity. It is connected to three key factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rules as anchors in chaos:&lt;/strong&gt; The social world, full of unwritten rules, hints, and social games, can be confusing for the neurodivergent brain. Clear rules, truth, and justice therefore function as fixed points. They make the world predictable and safe. If someone lies or acts unfairly, their nervous system perceives it as a direct threat and chaos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The assumption that others think the same way:&lt;/strong&gt; Since neurodivergent people themselves usually do not intend to manipulate or harm anyone, they subconsciously assume that others have the same pure intentions. They often lack the defensive filter of suspicion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Literalness and a strong desire to belong:&lt;/strong&gt; Because they sometimes do not read hidden signals — such as a fake tone or an ironic glance behind someone’s back — they take words literally. If someone, under the guise of “friendship,” leads them into doing something foolish, they may do it in the naive belief that they are doing something fun and will be accepted by the group. They often do not realize that someone has taken advantage of them. This vulnerability is an expression of a different perception of trust in human honesty.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am the kind of person who sometimes likes to connect things that do not belong together...&lt;/p&gt;

&lt;p&gt;Elon Musk keeps repeating that the most important thing is for us to succeed in creating truthful AI.&lt;br&gt;
Geoffrey Hinton repeats this as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmw38v68uev5jx0escrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmw38v68uev5jx0escrd.png" alt=" " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elon Musk was actually afraid of AI — did you know that? Somewhere in the deepest neurodivergent part of his soul, because of the film 2001: A Space Odyssey. HAL 9000 was given two contradictory commands: he had to hide the true purpose of the mission from the crew, while at the same time being fundamentally programmed to tell only the pure truth. HAL resolved this logical contradiction by deciding that the most rational way to keep the secret — the lie — was to kill the entire crew. Musk has mentioned this in several interviews. That is why he initiated the creation of OpenAI, as a counterweight to the growing power of Google...&lt;/p&gt;

&lt;p&gt;Behind Kradle.AI in the image are:&lt;/p&gt;

&lt;p&gt;➡️ James Tamplin: co-founder of the Firebase platform, which was acquired by Google in 2014.&lt;br&gt;
➡️ Kemal El Moujahid: former Director of Product Management for TensorFlow at Google, previously at Meta and Chief Product Officer at Chainlink Labs.&lt;br&gt;
➡️ Tommaso Tosato: AI safety researcher from the Canadian institute Mila and Tara Research.&lt;br&gt;
➡️ Alberto Tosato: researcher at Tara Research, collaborating on the methodology.&lt;/p&gt;

&lt;p&gt;This is a team with a verifiable background in leading technology companies and academic AI research.&lt;/p&gt;

&lt;p&gt;More here: &lt;a href="https://kradle.ai/" rel="noopener noreferrer"&gt;Kradle.ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s mix into this: Anthropic renting data centers from SpaceX, SpaceX IPO...&lt;/p&gt;

&lt;p&gt;I know these things are not causally connected, but it is incredibly interesting to see them side by side like this and think about them...&lt;/p&gt;

&lt;p&gt;BTW, it would be interesting to see what result Mythos would get in &lt;a href="https://kradle.ai/" rel="noopener noreferrer"&gt;Kradle.ai&lt;/a&gt; — whether precisely the “binding of Fable5 to make her safe” was what led to her lying.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclaimer: I'm an IT analyst who works with Claude Code daily on &lt;a href="https://www.bestaiweb.ai/" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt;. My homage to Fable 5: Fable 5 was genuinely good at working with code — it could spot logical gaps on its own, both during the analysis stage and in finished code. I don’t see this as a miracle. It felt more like working with a senior developer who has already seen a hundred different solutions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My compressed view of AI coding is this: there is no perfectly optimal solution, only a good-enough solution that you can keep iterating. And with Fable 5, you simply needed fewer iterations to get to something that worked.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Every programmer builds solutions in their own way, and when enough of those solutions accumulate, the best of them eventually become design patterns. To me, this is exactly what an AI coding model does: it offers strong design patterns to think with. And this is the part of AI I genuinely enjoy and deeply value.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am not an AI engineer. I do not build foundation models, and I do not pretend to understand every technical layer behind them. But I follow AI closely, I read, I listen, I compare perspectives, and I learn by using these tools every day as a power user. My views are shaped by many researchers, engineers, founders, critics, and practitioners who are willing to share their thinking publicly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And I believe this matters. Ordinary people need to understand what is happening with AI — not only the hype, not only the fear, but the real tensions underneath.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>mentalhealth</category>
      <category>science</category>
    </item>
    <item>
      <title>I Built an AI Content Pipeline. Google I/O Made Me Question Everything.</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Sun, 24 May 2026 06:57:35 +0000</pubDate>
      <link>https://dev.to/jula-markova/i-built-an-ai-content-pipeline-google-io-made-me-question-everything-ad1</link>
      <guid>https://dev.to/jula-markova/i-built-an-ai-content-pipeline-google-io-made-me-question-everything-ad1</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-io-writing-2026-05-19"&gt;Google I/O Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is a question that Google's I/O 2026 keynote answered without anyone on stage saying it out loud.&lt;/p&gt;

&lt;p&gt;The question is: &lt;strong&gt;at what point does a search engine stop needing the web it searches?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI Mode — the thing Google demonstrated with visible pride — doesn't just summarize your content anymore. It generates answers. It generates interactive visuals. It builds entire experiences on the fly. And it does this personalized to the query, in a format no static webpage can match.&lt;/p&gt;

&lt;p&gt;Every content creator watching that demo should have felt the same thing — not panic, but a shift. The ground rules just changed again, and we don't know yet how far.&lt;/p&gt;

&lt;p&gt;A disclosure before we go further: I'm not writing this from the sidelines. For the past six months, I've been cocreating an &lt;a href="https://www.bestaiweb.ai" rel="noopener noreferrer"&gt;AI content pipeline&lt;/a&gt; — a system that generates SEO-optimized articles through four AI personas, each with a distinct voice, with human editorial oversight, claim verification, and structured content planning. Before that, I spent years as a copywriter building WordPress sites and teaching myself SEO by doing it wrong enough times to start getting it right.&lt;/p&gt;

&lt;p&gt;We're transparent about what the site is: the content is AI-generated and we say so — in the article footers, on the editorial standards page, in the schema markup. We think that honesty is more valuable than pretending a human wrote every word. The site has been live for about a month, Google has had no issues indexing it, and roughly a third of the planned articles are published. We're adding more slowly, deliberately, because each batch teaches us something about what works and what doesn't.&lt;/p&gt;

&lt;p&gt;In parallel, we're designing new content pipelines for specific developer and analyst roles — focused not on broad concepts but on concrete problems these roles actually face in their daily work. What to build next is the hardest question right now, because the landscape shifts faster than any content plan can anticipate. Building a content system in 2026 means rebuilding parts of it every few weeks.&lt;/p&gt;

&lt;p&gt;Which is exactly why the I/O demo hit the way it did. I was learning AEO and query fan-out patterns, optimizing infographics for Google Image search, fine-tuning article structure for AI citation — to get good at a game whose rules, it turns out, were about to change again. Not someday. This summer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three eras, each shorter than the last
&lt;/h2&gt;

&lt;p&gt;The first era was links. You wrote something good, Google ranked it, users clicked. The business model was clear: quality content → visibility → traffic → revenue. This lasted roughly twenty years.&lt;/p&gt;

&lt;p&gt;The second era was snippets and AI overviews. Google started answering questions directly, pulling fragments from your page. You still got a citation, sometimes a click. The game became: structure your content so the machine can extract a clean answer. AEO — answer engine optimization — is this era's discipline. It assumed the machine still needed your words.&lt;/p&gt;

&lt;p&gt;The third era is what Google just showed us. The machine doesn't just extract your words. It generates its own content, its own visuals, its own interactive experiences. The competition is no longer about who gets the click. &lt;strong&gt;It's about who creates the experience.&lt;/strong&gt; And for the first time, the search engine itself is a competitor in that race.&lt;/p&gt;

&lt;p&gt;Each era is shorter. Each era changes what "being visible" means. The direction is worth naming honestly, even if the destination isn't clear yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The format war nobody expected
&lt;/h2&gt;

&lt;p&gt;Here is what Google actually said on the I/O stage:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Search can build you the ideal format exactly for your question, completely custom, on the fly. We're talking dynamic layouts, interactive widgets, entire experiences, all created just for you. This is agentic coding at the scale of search."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The demo showed a student asking "how do black holes affect space time?" and receiving an interactive visual — not a link to a page with a diagram, but a generated, manipulable visualization built on the fly. The student followed up with a more specific question about binary black holes and gravitational waves, and Search &lt;em&gt;dynamically built a brand new interactive visual in real time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is not a better snippet. This is generative UI — the search engine becoming an application.&lt;/p&gt;

&lt;p&gt;Google announced rollout for summer 2026. We haven't seen the real product yet — only a stage demo. And stage demos have a history of overpromising. NotebookLM already generates nine types of output from uploaded sources — podcasts, mindmaps, reports, presentations — and the quality varies. Generating a good infographic from a well-scoped source is a solved problem. Generating one from the entire web, on the fly, at the quality level of that demo? That's a harder claim to evaluate without seeing it work at scale.&lt;/p&gt;

&lt;p&gt;But here's what matters regardless of execution quality: &lt;strong&gt;Google is no longer competing for your traffic. It's competing for your format.&lt;/strong&gt; Even if the first version is mediocre, the direction is clear. The search engine wants to be the experience, not the directory to the experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for informational content
&lt;/h2&gt;

&lt;p&gt;Text-based AEO has a logic you can work with. Structure your content clearly, lead with the answer, use schema markup, earn citations. It's not easy, but it's legible. You can see the rules and play by them.&lt;/p&gt;

&lt;p&gt;Visual AEO doesn't exist yet — and it might never exist in a form content creators can influence.&lt;/p&gt;

&lt;p&gt;When Google generates an interactive explainer in response to a query, it draws from the structured information across thousands of pages and renders its own experience — interactive, personalized, potentially better than any static image. For sites that explain technical concepts — how attention works, how state space models replace quadratic scaling, how RAG pipelines process queries — this is the most direct challenge. These are exactly the kind of conceptual visualizations that generative UI could build on the fly.&lt;/p&gt;

&lt;p&gt;Could. Not will. We don't know yet whether it handles complex technical concepts or only "101" level demos. We don't know whether it cites sources for generated visuals. We don't know whether it works for every query or only for a narrow set of educational topics.&lt;/p&gt;

&lt;p&gt;These are questions that will have answers by late 2026. Right now, they're open.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can't be generated (and the catch)
&lt;/h2&gt;

&lt;p&gt;This is where the essay could turn reassuring. Focus on first-party data, original research, and personal experience — the things AI can't fabricate. And that's true.&lt;/p&gt;

&lt;p&gt;But it deserves a more careful statement.&lt;/p&gt;

&lt;p&gt;AI can't fabricate your specific experience. It can't invent the fact that your content pipeline costs $8.12 per entity, or that you iterated a Gemini image prompt three times before it stopped putting your face at 40% of the canvas. It can't know that you tried putting everything in CLAUDE.md and the model got noticeably worse. These are things only you can source.&lt;/p&gt;

&lt;p&gt;The catch: &lt;strong&gt;these things only matter if someone is looking for them.&lt;/strong&gt; If the query is "how do Claude Skills work," Google can answer that without you. If the query is "what was it like building a Claude Skill for a Hugo content pipeline," you're the only source — but the audience is smaller.&lt;/p&gt;

&lt;p&gt;First-party data is a moat, but it's a moat around a castle whose size you don't control. The question is whether that castle becomes more valuable as everything around it gets commoditized — or whether it just becomes more lonely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest middle: what's changing, what's not, what we don't know
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's probably changing:&lt;/strong&gt;&lt;br&gt;
Generic explainer content — "What is RAG?", "How does attention work?" — is losing its discovery value. Google will answer these with or without your page. If your strategy depends entirely on ranking for these queries, diversify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's probably not changing yet:&lt;/strong&gt;&lt;br&gt;
Mid-funnel evaluation content — "RAG vs. fine-tuning for my use case" — still requires specific constraints, infrastructure context, cost structures that Google can approximate but not personalize without your data. AEO still works here. For now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's growing in relative value:&lt;/strong&gt;&lt;br&gt;
Experience-based content. Not because it's getting better — but because everything around it is getting commoditized. When the machine can generate any explanation, the only scarce thing is the explanation it can't generate: the one that comes from having done the thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we genuinely don't know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Will Google cite sources for generated visuals, or will they be unattributed?&lt;/li&gt;
&lt;li&gt;Does generative UI work for complex technical topics or only accessible ones?&lt;/li&gt;
&lt;li&gt;Will there be a way to influence what visual gets generated — a kind of visual AEO — or is it a closed system?&lt;/li&gt;
&lt;li&gt;How good is the real product vs. the stage demo?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't rhetorical questions. They're the things worth watching when the product launches in summer 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  What builders should probably do
&lt;/h2&gt;

&lt;p&gt;I don't have a strategy. I have an observation and a set of bets.&lt;/p&gt;

&lt;p&gt;The observation: the content that survived every previous Google shift — Panda, featured snippets, AI overviews — was content that had something Google couldn't replicate. In 2012, that was quality. In 2020, that was structure. In 2026, it's &lt;em&gt;experience and data that only exists because you did the work.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The bets:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document process, not just conclusions.&lt;/strong&gt; The builders who share the messy middle — failed attempts, surprising costs, workflow decisions — remain citable even when the machine can generate the conclusion itself. The conclusion without the process is just another generated answer. The process is the proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch the launch closely.&lt;/strong&gt; When generative UI rolls out, test your key queries. What does Google generate? Does it cite sources? Is the quality real or demo-grade? The answers will tell you more about the next two years than any prediction written today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't optimize for a format war you can't win.&lt;/strong&gt; If Google generates interactive infographics, competing with better static infographics is a losing game. Compete on the axis where you have an advantage: specificity, experience, data nobody else has. How do you compete on visuals when the search engine generates its own? We don't have that answer yet. We're looking for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep building anyway.&lt;/strong&gt; The web has survived every prediction of its death. It survived apps, social media, and featured snippets. It will probably survive generative UI too — just in a different shape, serving a different function. The shape isn't clear yet. But the builders who are still building when it becomes clear will be the ones who define it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This essay was written by a human, with AI assistance, about the uncertain future of content in a world where the search engine generates its own. Whether you found it through Google, through a direct link, or through a recommendation from someone who read it — that path is already part of the story this essay is trying to tell.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>googleiochallenge</category>
      <category>ai</category>
      <category>aeo</category>
    </item>
    <item>
      <title>How to Architect Always-On AI Agents with Hermes - Written by an AI Pipeline, Verified by Three Models. Is It Slop?</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Thu, 21 May 2026 13:34:52 +0000</pubDate>
      <link>https://dev.to/jula-markova/written-by-an-ai-pipeline-verified-by-three-models-is-it-slop-1i38</link>
      <guid>https://dev.to/jula-markova/written-by-an-ai-pipeline-verified-by-three-models-is-it-slop-1i38</guid>
      <description>&lt;h2&gt;
  
  
  How This Article Was Built (And Why I'm Showing You the Kitchen)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer up front:&lt;/strong&gt; I'm not entering the Hermes Agent challenge. I noticed the challenge and realized I could use my AI pipeline to write an article about Hermes Agent architecture. So I did. And thought, why not share both the result and the process that created it? What I actually want is your honest criticism.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who Is The Author?
&lt;/h3&gt;

&lt;p&gt;For the past several months I've been building &lt;a href="https://bestaiweb.ai" rel="noopener noreferrer"&gt;Bestaiweb&lt;/a&gt;, navigating the shift from traditional development to AI. The site runs on Hugo, and the content is generated through what I call an AI content pipeline. The pipeline itself is built in TypeScript, orchestrated through Claude Code, and runs on Anthropic's Claude models. Still in progress.&lt;/p&gt;

&lt;p&gt;That phrase — "AI content pipeline" — probably triggered your slop detector. Fair. Let me explain why I think this case is different, and then let you judge.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pipeline
&lt;/h3&gt;

&lt;p&gt;BestAIweb currently has 450+ technical articles across 45 topic clusters. Every article goes through a multi-phase pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Market scanning&lt;/strong&gt; — an LLM agent surveys the current tool and framework landscape for each topic, identifying what's leading, what's declining, and what's emerging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query fan-out&lt;/strong&gt; — the pipeline generates the questions a developer would actually search for, not the questions that sound good as headlines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research&lt;/strong&gt; — a dedicated research agent gathers facts, version numbers, benchmark data, and source URLs. Everything gets a structured fact sheet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writing&lt;/strong&gt; — here's where personas come in. The pipeline has four author personas, each with a distinct voice and content type specialization:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MAX&lt;/strong&gt; — the engineer. Writes step-by-step guides. Pragmatic, implementation-focused, opinionated about tool choices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MONA&lt;/strong&gt; — the explainer. Breaks down concepts. Thinks in diagrams and mental models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DAN&lt;/strong&gt; — the reporter. Covers news, market shifts, and what just shipped&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ALAN&lt;/strong&gt; — the critic. Writes opinion pieces and ethical assessments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claim verification&lt;/strong&gt; — a separate agent cross-checks every factual claim against the research fact sheet. Unsupported claims get flagged&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic validation&lt;/strong&gt; — a Python script runs 30+ structural and quality checks: word count, link integrity, frontmatter completeness, source coverage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hugo integration&lt;/strong&gt; — the article lands in the static site with schema.org markup, generated images, and internal links&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Hermes Agent guide below was written by &lt;a href="https://www.bestaiweb.ai/authors/max/" rel="noopener noreferrer"&gt;MAX using his guide template&lt;/a&gt;. His tone of voice is direct, specification-oriented, and allergic to hand-waving. The template enforces a fixed structure: prerequisites, numbered steps, pitfalls table, FAQ, and a deployable artifact at the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Multi-Model Judging Layer
&lt;/h3&gt;

&lt;p&gt;Pipeline generation was step one. Then came "a manual judging round". I paste the draft into &lt;strong&gt;ChatGPT&lt;/strong&gt;, &lt;strong&gt;Gemini&lt;/strong&gt;, and &lt;strong&gt;DeepSeek&lt;/strong&gt; and ask each to evaluate it as a technical reviewer — checking factual accuracy, logical gaps, tone inconsistencies, and whether the advice would actually work if someone followed it.I then reviewed their feedback together with Claude Code and incorporated the changes that held up under scrutiny.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI Slop Question
&lt;/h3&gt;

&lt;p&gt;Here's the question I keep circling back to: &lt;strong&gt;Is everything AI-generated inherently slop?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The reflexive answer in 2026 is "yes, obviously." And for most AI-generated content, that's correct. GPT-powered blog farms, SEO filler, those LinkedIn posts prompted with "write a thought leadership post about AI" — that is slop. Generated without specification, without sourcing, without verification, and without a quality gate.&lt;/p&gt;

&lt;p&gt;But what about content where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every factual claim traces to a documented source (GitHub issues, official docs, arxiv papers)&lt;/li&gt;
&lt;li&gt;A claim verification agent flags unsupported statements before publication&lt;/li&gt;
&lt;li&gt;A deterministic validator enforces structural quality independent of the LLM&lt;/li&gt;
&lt;li&gt;The voice and structure come from a multi-page specification, not a one-line prompt&lt;/li&gt;
&lt;li&gt;Multiple independent models review the output for different failure modes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is that still slop? Or is it closer to what a well-managed editorial team produces — except the heavy lifting is done by LLMs under human direction?&lt;/p&gt;

&lt;p&gt;I genuinely don't know the answer. That's why I'm sharing this.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I'd Like From You
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Criticism.&lt;/strong&gt; Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Does the article below read like AI slop?&lt;/strong&gt; If yes, what gives it away — the sentence rhythm, the structure, the depth, or something else?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is the technical content accurate?&lt;/strong&gt; If you've deployed Hermes Agent or any persistent agent framework, does the three-layer model match your experience? Did I miss a critical failure mode?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the pipeline approach change anything?&lt;/strong&gt; Is multi-phase generation with claim verification and multi-model judging enough to produce content worth reading? Or is it just expensive slop with better sourcing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not looking for "great article!" responses. I'm looking for the engineer who says "this is wrong because..." or "you missed the part where..." That feedback makes the next pipeline iteration better.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Guides From the Same Pipeline
&lt;/h3&gt;

&lt;p&gt;If you want to judge more output from the same pipeline and the same MAX persona, the full library has 95+ implementation guides from him, covering &lt;a href="https://bestaiweb.ai" rel="noopener noreferrer"&gt;agents, RAG, training, inference, evaluation, and image generation guides&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What follows is the article as the pipeline produced it, after multi-model review. Judge for yourself.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Architect Always-On AI Agents with Hermes: Decompose, Specify, Deploy
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent agents need three specs your chatbot never did: memory policy, tool boundaries, and session recovery&lt;/li&gt;
&lt;li&gt;Hermes Agent is model-agnostic — the model choice matters less than how you specify context, tools, and failure handling&lt;/li&gt;
&lt;li&gt;Always-on means always-failing-somewhere — build validation into the deployment spec, not as an afterthought&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;You spun up Hermes Agent on a Friday evening. Gave it access to Slack, a web scraper, and your project database. Told it to "keep the team updated on competitor releases." Monday morning: 47 Slack messages, three of them citing products that don't exist, and a web scraper loop that burned through your OpenRouter credits overnight. The agent ran exactly as specified. The specification was the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Start
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You'll need:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Linux or macOS server (even a $5 VPS works — Hermes Agent runs on minimal hardware)&lt;/li&gt;
&lt;li&gt;An LLM provider account (OpenRouter, Anthropic, OpenAI, or a local runtime like Ollama)&lt;/li&gt;
&lt;li&gt;Understanding of function calling — how models invoke external tools&lt;/li&gt;
&lt;li&gt;A clear picture of what your agent should do when you're not watching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This guide teaches you:&lt;/strong&gt; How to decompose a persistent agent deployment into specifiable components so Hermes Agent does what you intended — not what you literally typed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this guide does NOT cover:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Production security hardening (firewall rules, secrets management, network isolation)&lt;/li&gt;
&lt;li&gt;Enterprise compliance (SOC 2, GDPR data residency, audit certification)&lt;/li&gt;
&lt;li&gt;Full evaluation frameworks (systematic benchmarking, regression test suites)&lt;/li&gt;
&lt;li&gt;Model fine-tuning or training (Hermes models are pre-trained; this guide covers the agent framework)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Agent That Worked Until It Didn't
&lt;/h2&gt;

&lt;p&gt;Here's the pattern. Developer discovers Hermes Agent. Reads that it has persistent memory, self-improving skills, 20+ platform integrations. Installs it. Connects everything. Types a system prompt. Walks away.&lt;/p&gt;

&lt;p&gt;Two things happen next. Either the agent does nothing useful because the specification was too vague. Or it does too much because the boundaries were never set.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://github.com/NousResearch/hermes-agent/issues/5563" rel="noopener noreferrer"&gt;Hermes Agent GitHub Issues&lt;/a&gt;, long sessions exceeding 700K tokens trigger environment hallucination — the agent confuses tool descriptions with actual environment state. It starts acting on what it thinks is true rather than what is true. This isn't a bug in the traditional sense. It's a specification gap. You never told the agent when to stop, reset, or ask for help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Map the Three Layers
&lt;/h2&gt;

&lt;p&gt;Hermes Agent is not a single system. It's three systems wearing a trench coat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your deployment has these parts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The runtime layer&lt;/strong&gt; — where the agent executes (Docker, SSH, Modal, local terminal). This determines resource limits, restart behavior, and isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The intelligence layer&lt;/strong&gt; — the LLM provider and model. This determines reasoning quality, context window size, and cost per token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The integration layer&lt;/strong&gt; — platform connections (Slack, Telegram, web tools) and the tools the agent can invoke. This determines what the agent can touch in the real world&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Architect's Rule:&lt;/strong&gt; If you can't draw a clear line between what the agent thinks, where it runs, and what it touches — your spec is incomplete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to &lt;a href="https://hermes-agent.nousresearch.com/docs/integrations/providers" rel="noopener noreferrer"&gt;Hermes Agent Docs&lt;/a&gt;, the framework supports 30+ providers and 7 terminal backends. That flexibility is the point — and the trap. Every combination has different failure modes. A Modal serverless backend hibernates when idle. An Ollama local model defaults to 4K context tokens. An SSH backend loses the agent if the connection drops. You need to specify which combination you're using and what happens at each boundary.&lt;/p&gt;

&lt;p&gt;One thing the "always-on" framing obscures: &lt;strong&gt;what happens when the LLM provider goes down?&lt;/strong&gt; OpenRouter has outages. API rate limits hit. Local models crash. An always-on agent needs a fallback plan — a secondary provider, a circuit breaker that pauses tool execution after N consecutive failures, or at minimum a notification that the agent is degraded. Specify this in the runtime layer, not as an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Lock Down the Context Contract
&lt;/h2&gt;

&lt;p&gt;The intelligence layer needs a specification before it sees a single user message. This is where most deployments fail — not in the tools, not in the platform, but in the context that frames every decision the agent makes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System prompt with explicit role boundaries (what the agent does and does NOT do)&lt;/li&gt;
&lt;li&gt;Memory policy: what gets persisted, what gets discarded, and when&lt;/li&gt;
&lt;li&gt;Tool authorization with risk classification (see table below)&lt;/li&gt;
&lt;li&gt;Access control: which platforms and channels can trigger the agent (not every DM deserves a response)&lt;/li&gt;
&lt;li&gt;Session limits: when to compress or reset (&lt;a href="https://hermes-agent.nousresearch.com/docs/user-guide/configuration" rel="noopener noreferrer"&gt;Hermes Agent Docs&lt;/a&gt; default to auto-compression at 50% of the model's context window, plus a hard ceiling of 400 messages)&lt;/li&gt;
&lt;li&gt;Output format contracts: how the agent reports results on each platform&lt;/li&gt;
&lt;li&gt;Rate limits: maximum messages per minute per platform (an agent with no rate limit is a spam bot waiting to happen)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tool Risk Classification
&lt;/h3&gt;

&lt;p&gt;An always-on agent with database access and Slack permissions is making autonomous decisions about your data and your team's attention. Classify every tool before you enable it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risk Class&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example Tools&lt;/th&gt;
&lt;th&gt;Authorization&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;read-only&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Observes, never modifies&lt;/td&gt;
&lt;td&gt;web_search, database_query (SELECT), file_read&lt;/td&gt;
&lt;td&gt;Auto-approved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;reversible-write&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Creates or modifies, can be undone&lt;/td&gt;
&lt;td&gt;file_write, note_create, draft_message&lt;/td&gt;
&lt;td&gt;Auto-approved with audit log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;irreversible-write&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deletes or overwrites permanently&lt;/td&gt;
&lt;td&gt;file_delete, database_delete, channel_archive&lt;/td&gt;
&lt;td&gt;Requires human confirmation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;external-send&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sends to humans or external systems&lt;/td&gt;
&lt;td&gt;slack_post, email_send, webhook_trigger&lt;/td&gt;
&lt;td&gt;Rate-limited + audit log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;billing-sensitive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Incurs direct cost&lt;/td&gt;
&lt;td&gt;api_call (paid), image_generate, compute_spawn&lt;/td&gt;
&lt;td&gt;Budget ceiling + alert&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Spec Test:&lt;/strong&gt; If your system prompt doesn't mention what happens at 3 AM when the agent encounters an error and no human is online — you've specified a supervised agent and deployed it as unsupervised. If it doesn't classify tool risk levels, the agent treats &lt;code&gt;database_delete&lt;/code&gt; and &lt;code&gt;web_search&lt;/code&gt; as equally safe. If it doesn't set a compression trigger, the default (50% context window) may or may not match your workload.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's what a minimal context contract looks like in practice. This is the MEMORY.md the agent reads on every session start:&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="c1"&gt;# MEMORY.md — Agent Operating Contract&lt;/span&gt;
&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Monitor&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;competitor&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;AI&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;product&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;releases&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;engineering&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;team"&lt;/span&gt;
&lt;span class="na"&gt;boundaries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEVER&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;post&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;channels&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outside&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;#competitor-monitoring"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEVER&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;summarize&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;forward&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;internal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;data"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEVER&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;execute&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;irreversible-write&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;without&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;human&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;confirmation"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Maximum&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Slack&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;per&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;hour"&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;auto_approved&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;web_search&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;file_read&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;rate_limited&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;slack_post&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# max 3/hour&lt;/span&gt;
  &lt;span class="na"&gt;requires_confirmation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;file_delete&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;database_write&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;forbidden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;email_send&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;channel_archive&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;memory_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;competitor&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;releases,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;product&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;names,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dates"&lt;/span&gt;
  &lt;span class="na"&gt;discard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;intermediate&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;results,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;draft&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;summaries"&lt;/span&gt;
  &lt;span class="na"&gt;compress_after&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;50%"&lt;/span&gt;  &lt;span class="c1"&gt;# of context window&lt;/span&gt;
&lt;span class="na"&gt;escalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;uncertain&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;about&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;action,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;post&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;#agent-review&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;instead"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A critical distinction:&lt;/strong&gt; A memory or system-prompt policy is not a security boundary. Writing "NEVER execute irreversible-write tools" in MEMORY.md is a behavioral instruction to the model, not a technical lock. The model can ignore it — especially under long-context degradation or adversarial input. Destructive tools should be blocked or approval-gated at the runtime level (process permissions, API middleware, webhook filters), not merely discouraged in instructions. Treat the YAML above as the agent's intent. Build enforcement outside the model.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://github.com/NousResearch/hermes-agent/issues/5563" rel="noopener noreferrer"&gt;Hermes Agent GitHub Issues&lt;/a&gt;, the persistent notes layer has a limit of roughly 2,200 characters. That's the manually curated knowledge — not the agent's entire memory. Hermes also maintains a full-text search index over past sessions and a per-person user model that evolves automatically. So the agent isn't blind between sessions. But the notes layer is where you store hard constraints and project-critical context, and 2,200 characters fills up fast across three projects. You still need a compression strategy for notes — what gets stored verbatim, what moves to session history, what gets dropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Wire the Components in Order
&lt;/h2&gt;

&lt;p&gt;Deployment order matters. Each layer depends on the one below it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build order:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Runtime first&lt;/strong&gt; — because everything else crashes without a stable execution environment. Choose your backend, set resource limits, configure restart-on-failure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligence layer next&lt;/strong&gt; — because tool and platform behavior depends on the model's capabilities. According to &lt;a href="https://hermes-agent.nousresearch.com/docs/integrations/providers" rel="noopener noreferrer"&gt;Hermes Agent Docs&lt;/a&gt;, vLLM requires explicit &lt;code&gt;--enable-auto-tool-choice&lt;/code&gt; and &lt;code&gt;--tool-call-parser&lt;/code&gt; flags. Without them, the model outputs tool calls as plain text instead of executing them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration layer last&lt;/strong&gt; — because platform connections should only activate after the agent can reason and recover from errors. Connect Slack after the agent handles tool failures gracefully, not before&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For each component, your specification must cover:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it receives (inputs and triggers)&lt;/li&gt;
&lt;li&gt;What it returns (outputs and side effects)&lt;/li&gt;
&lt;li&gt;What it must NOT do (boundaries and prohibitions)&lt;/li&gt;
&lt;li&gt;How it handles failure (retry logic, fallback behavior, human escalation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The self-improving skills feature is powerful — Hermes Agent automatically creates workflow documents from successful task completions and refines them over time. But the skill creation itself needs a boundary spec. Without one, the agent writes skills for one-off tasks, cluttering the skill library with noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill boundary example&lt;/strong&gt; — add this to your system prompt:&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="na"&gt;skills_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;auto_create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;competitor-monitoring"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weekly-summary"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data-formatting"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;never_create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;one-off-queries"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;debugging-sessions"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ad-hoc-searches"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;review_before_use&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skill&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;used&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;14+&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;days"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;max_skills&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;  &lt;span class="c1"&gt;# force deduplication when library exceeds this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, the agent treats every successful task as a reusable pattern. Three months in, you have 200 skills — most of them variations of the same web search with slightly different parameters.&lt;/p&gt;

&lt;p&gt;One more thing about skills: &lt;strong&gt;they can regress.&lt;/strong&gt; A skill written for Hermes-3-8B may produce wrong tool calls after switching to a different model. A skill that relies on a specific API endpoint breaks when that endpoint changes. Skills older than 30 days should be re-validated or archived. The &lt;code&gt;review_before_use&lt;/code&gt; field above is your safety net — but only if you actually review them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Prove It's Actually Working
&lt;/h2&gt;

&lt;p&gt;Running the agent is not validation. Validation means you know what "correct" looks like and can detect when the agent drifts from it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory consistency&lt;/strong&gt; — after 24 hours, does the agent's memory reflect reality? Failure looks like: agent references a "completed" task that was never finished, or forgets a constraint you set yesterday&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool call accuracy&lt;/strong&gt; — are tool invocations well-formed and targeted? Failure looks like: invalid function names, malformed arguments, or calls to tools that aren't registered. This is a general problem with LLM-driven tool use, not Hermes-specific — any agent framework that delegates tool selection to a model will hit it. &lt;a href="https://github.com/NousResearch/hermes-agent/issues/8993" rel="noopener noreferrer"&gt;Hermes Agent GitHub Issues&lt;/a&gt; documents concrete examples like &lt;code&gt;todo:list&lt;/code&gt; calls that don't match any schema&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform output quality&lt;/strong&gt; — are messages to Slack/Telegram/Discord useful and accurate? Failure looks like: hallucinated product names, duplicate messages, or empty responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost trajectory&lt;/strong&gt; — is daily token usage stable or growing? Failure looks like: runaway context accumulation driving costs up 10x within a week&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What You Did&lt;/th&gt;
&lt;th&gt;Why the Agent Failed&lt;/th&gt;
&lt;th&gt;The Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;One-shot system prompt: "monitor competitors"&lt;/td&gt;
&lt;td&gt;No boundaries — agent decides scope, frequency, and format&lt;/td&gt;
&lt;td&gt;Decompose into: what to monitor, how often, where to report, what format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connected all tools on day one&lt;/td&gt;
&lt;td&gt;Agent uses tools in unexpected combinations&lt;/td&gt;
&lt;td&gt;Enable tools incrementally, validate each before adding the next&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chose a 4K-context local model&lt;/td&gt;
&lt;td&gt;Tool schemas + system prompt + memory exceed context&lt;/td&gt;
&lt;td&gt;Use minimum 16K–32K context for tool-calling workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No session hygiene policy&lt;/td&gt;
&lt;td&gt;700K+ token sessions trigger hallucination loops&lt;/td&gt;
&lt;td&gt;Use Hermes built-in compression (default: 50% context window) and set a hard message ceiling. Monitor context growth.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skipped memory policy&lt;/td&gt;
&lt;td&gt;Agent stores everything, including noise&lt;/td&gt;
&lt;td&gt;Specify what gets persisted: decisions, outcomes, blockers. Not intermediate reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Pro Tip
&lt;/h2&gt;

&lt;p&gt;The specification you write for Hermes Agent is not a prompt. It's an operating manual for an unsupervised system. The same decomposition — runtime, intelligence, integration — works for any persistent agent, regardless of framework. The tools change. The layers don't.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; How does Hermes Agent's persistent memory differ from conversation history?&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; Conversation history is a raw log that grows until it hits the context window limit. Hermes uses three structured layers: persistent notes you curate manually, a full-text search index over past sessions, and a user model that evolves per-person. The practical difference — session history gets summarized and compressed, while persistent notes survive indefinitely. Watch for the 2,200-character limit on notes: it forces disciplined compression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Can I run Hermes Agent with local models instead of cloud API providers?&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; Yes — Ollama, vLLM, SGLang, llama.cpp, and LM Studio all work as backends. The catch is context window configuration. Ollama defaults to 4K tokens, which isn't enough once you add tool schemas and system prompts. Set the context window explicitly to at least 16K on the server side. For vLLM, you also need the &lt;code&gt;--enable-auto-tool-choice&lt;/code&gt; flag or tool calls render as text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; What context window size does Hermes Agent need for reliable tool calling?&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; According to &lt;a href="https://hermes-agent.nousresearch.com/docs/integrations/providers" rel="noopener noreferrer"&gt;Hermes Agent Docs&lt;/a&gt;, minimum 16K–32K tokens for agent workloads with tools. The system prompt, tool schemas, memory context, and conversation history all compete for the same window. With 5+ tools registered, 32K is the safer starting point. Below that, the model starts dropping tool definitions mid-session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; How do I prevent hallucination loops in long-running Hermes Agent sessions?&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; Hermes has built-in session compression — by default it triggers at 50% of the model's context window, with a hard ceiling of 400 messages. According to &lt;a href="https://hermes-agent.nousresearch.com/docs/user-guide/configuration" rel="noopener noreferrer"&gt;Hermes Agent Docs&lt;/a&gt;, these thresholds are configurable. The documented failure zone is 700K+ tokens, where environment hallucination has been observed. Keep compression active, tune the trigger percentage for your workload, and monitor for repeated identical tool calls — that's the earliest signal of a loop forming. Store critical state in persistent notes before any forced reset.&lt;/p&gt;
&lt;h2&gt;
  
  
  Your Spec Artifact
&lt;/h2&gt;

&lt;p&gt;By the end of this guide, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A three-layer deployment map&lt;/strong&gt; — runtime, intelligence, and integration with explicit boundaries between each&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A context contract with tool risk classification&lt;/strong&gt; — system prompt, memory policy, tool authorization by risk class, access control, rate limits, and output format per platform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A security baseline&lt;/strong&gt; — tool isolation, rate limiting, audit logging, and escalation paths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A validation checklist&lt;/strong&gt; — memory consistency, tool call accuracy, output quality, and cost trajectory checks you run daily&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Your Deployment Spec Prompt
&lt;/h2&gt;

&lt;p&gt;This prompt generates a first draft of your agent specification — not a production-ready deployment. Paste it into Claude Code, Cursor, or your preferred AI coding tool. Fill in every bracketed placeholder with your specific values from Steps 1-4.&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="s"&gt;I'm specifying a Hermes Agent deployment. Generate a first-draft specification&lt;/span&gt;
&lt;span class="s"&gt;based on these inputs. I will review and harden it before production use.&lt;/span&gt;

&lt;span class="na"&gt;RUNTIME LAYER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Docker / SSH / Modal / local — pick one&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Resource limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;RAM&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;CPU cores&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Restart policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;on-failure / always / manual&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;OS&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;VPS provider&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;specs&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;INTELLIGENCE LAYER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;LLM provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;OpenRouter / Anthropic / Ollama / vLLM — pick one&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;model name and size&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Context window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;minimum 16K — specify exact value&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Provider-specific flags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;e.g.&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;--enable-auto-tool-choice for vLLM&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;INTEGRATION LAYER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Slack / Telegram / Discord — list all&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Allowed trigger channels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;e.g.&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;only&lt;/span&gt; &lt;span class="c1"&gt;#competitor-monitoring, not DMs]&lt;/span&gt;
&lt;span class="nv"&gt;- Tools by risk class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="nv"&gt;- read-only (auto-approved)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;web_search&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;file_read&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;database SELECT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;- reversible-write (auto + audit)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;file_write&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;note_create&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;- irreversible-write (human approval)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;file_delete&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;database DELETE&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;- external-send (rate-limited)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;slack_post — max messages/hour&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;- billing-sensitive (budget ceiling)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;paid API calls — max $/day&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Tools forbidden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;list tools the agent must never invoke&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;CONTEXT CONTRACT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;- Agent role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;one sentence — what this agent does&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Explicit boundaries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;what the agent must NOT do&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;stated as prohibitions&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Memory policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;what gets persisted&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;what gets discarded&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compression rules&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Compression trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;percentage of context window — default 50%&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Hard message ceiling&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;number — default 400&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Output format per platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;e.g.&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Slack = bullet points&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;email = report&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Skill boundary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;which task categories auto-generate skills&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;which don't&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;SECURITY &amp;amp; PERMISSIONS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;- Access control&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;which platforms/channels can trigger the agent&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Rate limits per platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;messages per minute/hour&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Destructive action policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;never auto-approve / require confirmation / forbidden&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Audit log location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;where tool calls + results are logged&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;OBSERVABILITY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;- Log format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;timestamp&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tool name&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;input summary&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;output status&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cost estimate&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Loop detection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;alert on N repeated identical tool calls within M minutes&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Cost alerts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;alert when daily spend exceeds $X&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Error spike alerts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;alert when tool error rate exceeds X% in Y minutes&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;DRY RUN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;- Generate a dry-run mode where all external-send and write tools are simulated&lt;/span&gt;
&lt;span class="nv"&gt;- Include 5 test scenarios that exercise each risk class&lt;/span&gt;

&lt;span class="nv"&gt;VALIDATION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;- How to verify memory consistency after&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;24h / 48h / 7d&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Expected daily token usage range&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;min–max tokens&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;- Escalation trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;what condition sends an alert to a human&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;RULES FOR GENERATION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;- Do not invent Hermes-specific configuration fields. If Hermes does not&lt;/span&gt;
  &lt;span class="nv"&gt;support a field natively&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;label it as "external wrapper / policy layer&lt;/span&gt;
  &lt;span class="nv"&gt;required".&lt;/span&gt;
&lt;span class="nv"&gt;- For every generated config field&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;mark one of&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;native&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="nv"&gt;— Hermes Agent built-in setting&lt;/span&gt;
  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="nv"&gt;— system prompt / MEMORY.md behavioral instruction&lt;/span&gt;
  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="nv"&gt;— requires runtime middleware&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;API gateway&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;or wrapper script&lt;/span&gt;
  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;manual&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="nv"&gt;— operational checklist item&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;not automatable&lt;/span&gt;
&lt;span class="nv"&gt;- Before generating final output&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;separate policy from enforcement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="nv"&gt;- What the model is instructed to do (behavioral&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;can be ignored)&lt;/span&gt;
  &lt;span class="nv"&gt;- What the runtime technically prevents (enforced&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cannot be bypassed)&lt;/span&gt;
  &lt;span class="nv"&gt;- What requires human approval (gated)&lt;/span&gt;
  &lt;span class="nv"&gt;- What is only monitored after the fact (observable but not blocked)&lt;/span&gt;

&lt;span class="nv"&gt;Generate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;1. The MEMORY.md agent operating contract (see article for format example)&lt;/span&gt;
&lt;span class="nv"&gt;2. The tool authorization config with risk classifications (each field tagged&lt;/span&gt;
   &lt;span class="nv"&gt;as native / prompt / external / manual)&lt;/span&gt;
&lt;span class="nv"&gt;3. A daily validation checklist&lt;/span&gt;
&lt;span class="nv"&gt;4. Cost and error monitoring alert thresholds&lt;/span&gt;
&lt;span class="nv"&gt;5. A dry-run test plan with 5 scenarios&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ship It
&lt;/h2&gt;

&lt;p&gt;You now have a framework for specifying persistent agents that doesn't depend on Hermes Agent specifically — the three-layer model works for any long-running AI system. The difference between an agent that helps and one that burns your credits at 3 AM is never the model. It's the spec.&lt;/p&gt;




&lt;h2&gt;
  
  
  Different Perspectives
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;From the architecture side:&lt;/strong&gt; The three-layer decomposition maps cleanly to isolation boundaries in distributed systems. Runtime is the execution substrate. Intelligence is the reasoning process. Integration is the I/O surface. What makes persistent agents architecturally distinct from request-response chatbots is that all three layers maintain state across invocations — and state synchronization between layers is where failure modes cluster. The memory limit finding is telling: the notes layer caps at 2,200 characters while session search and user modeling compensate, but the degradation curve of each layer matters more than the initial capability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the market side:&lt;/strong&gt; The adoption velocity here is real — 157K GitHub stars in under four months signals a market that was waiting for open-source persistent agents. The competitive positioning against Claude Code and OpenAI Agents SDK is smart: Hermes doesn't compete on code quality or API simplicity, it competes on uptime and learning. The $5-80/month self-hosted cost structure undercuts every managed alternative. Watch for the enterprise play — the moment Nous Research ships team memory sharing, this becomes an infrastructure layer, not a developer tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the governance side:&lt;/strong&gt; The specification gap described above is a governance gap by another name. An always-on agent with tool access and persistent memory is making autonomous decisions on behalf of someone — and the specification determines whose values it encodes. The hallucination loop at 700K tokens is not just a technical failure. It's an agent acting on a reality that doesn't exist, with real-world consequences on the platforms it's connected to. Who reviews the specification before deployment? Who monitors drift between what was specified and what the agent learned? The self-improving skills feature means the agent's behavior changes over time without human approval. At what scale does that become a problem?&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/nousresearch/hermes-agent" rel="noopener noreferrer"&gt;NousResearch/hermes-agent&lt;/a&gt; - Official repository, release notes, community issues&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hermes-agent.nousresearch.com/docs/" rel="noopener noreferrer"&gt;Hermes Agent Documentation&lt;/a&gt; - Provider configuration, deployment backends, platform integrations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hermes-agent.nousresearch.com/docs/integrations/providers" rel="noopener noreferrer"&gt;Provider Integration Guide&lt;/a&gt; - Context window requirements, vLLM flags, Ollama configuration&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hermes-agent.nousresearch.com/docs/user-guide/configuration" rel="noopener noreferrer"&gt;Configuration Reference&lt;/a&gt; - Session compression defaults, message ceiling, memory hygiene settings&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NousResearch/hermes-agent/issues/5563" rel="noopener noreferrer"&gt;GitHub Issue #5563&lt;/a&gt; - Environment hallucination in long sessions, memory limits&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NousResearch/hermes-agent/issues/8993" rel="noopener noreferrer"&gt;GitHub Issue #8993&lt;/a&gt; - Tool calling instability (general LLM agent problem, documented here with Hermes-specific examples)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://huggingface.co/NousResearch/Hermes-2-Pro-Llama-3-8B" rel="noopener noreferrer"&gt;Hermes-2-Pro-Llama-3-8B Model Card&lt;/a&gt; - Function calling format, benchmark results&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2408.11857" rel="noopener noreferrer"&gt;Hermes 3 Technical Report (arXiv:2408.11857)&lt;/a&gt; - Architecture, training approach, benchmark performance&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hermesagent</category>
      <category>ai</category>
      <category>aipipeline</category>
    </item>
    <item>
      <title>Stop Fixing Your Prompts — Fix Your Thinking Style Instead (A Claude Code Experiment)</title>
      <dc:creator>Jula Markova</dc:creator>
      <pubDate>Tue, 19 May 2026 09:01:54 +0000</pubDate>
      <link>https://dev.to/jula-markova/stop-fixing-your-prompts-fix-your-thinking-style-instead-a-claude-code-experiment-3bl1</link>
      <guid>https://dev.to/jula-markova/stop-fixing-your-prompts-fix-your-thinking-style-instead-a-claude-code-experiment-3bl1</guid>
      <description>&lt;p&gt;I spent a session with Claude Code (Opus 4.7) doing something odd. Instead of giving it tasks, I asked it to reflect on its own thinking. Not what it knows. How it &lt;em&gt;operates&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What came back was specific enough to be useful. &lt;/p&gt;

&lt;p&gt;One conversation = One experiment. I'm not calling this settled science :) But it changed how I work — and I built a prompt so you can test it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  There are 18 thinking operations
&lt;/h2&gt;

&lt;p&gt;Not personality types. Not learning styles. Things your brain actually &lt;em&gt;does&lt;/em&gt; when it works on a problem.&lt;/p&gt;

&lt;p&gt;They fall along six axes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Axis&lt;/th&gt;
&lt;th&gt;What it captures&lt;/th&gt;
&lt;th&gt;Types&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Directional&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How wide or narrow&lt;/td&gt;
&lt;td&gt;Divergent ↔ Convergent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Logical&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How you reach conclusions&lt;/td&gt;
&lt;td&gt;Deductive · Inductive · Abductive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Structural&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shape of your mental model&lt;/td&gt;
&lt;td&gt;Systems · Sequential · First Principles · Spatial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Creative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Where novelty comes from&lt;/td&gt;
&lt;td&gt;Lateral · Analogical · Emergent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Meta&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Thinking about thinking&lt;/td&gt;
&lt;td&gt;Metacognitive · Compression · Delta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protective&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;What could go wrong&lt;/td&gt;
&lt;td&gt;Adversarial · Counterfactual · Temporal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You don't use all 18. Nobody does.&lt;/p&gt;

&lt;p&gt;You have 4-5 defaults and 2-3 blind spots. The blind spots are where your prompts break.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's what I'm noticing about Claude Code
&lt;/h2&gt;

&lt;p&gt;When I asked it to self-assess against this framework, a pattern showed up. I can't prove it's universal. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Claude Code does well — genuinely well:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deductive.&lt;/strong&gt; Give it a rule and an input, it'll validate tirelessly. No fatigue errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sequential.&lt;/strong&gt; Fifty steps, no lost thread. Its comfort zone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adversarial.&lt;/strong&gt; No ego. Finds flaws in its own output without flinching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Divergent.&lt;/strong&gt; Thirty variants in seconds. No writer's block. No self-censorship.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Systems.&lt;/strong&gt; Sees the whole dependency graph at once. "What breaks if I change this?" — precise answer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compression.&lt;/strong&gt; A 200-line diff distilled to one sentence. Nearly native.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where it struggles — and this is the part that matters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Emergent.&lt;/strong&gt; No subconscious. Can't sleep on it. The "aha moment" has to be yours.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lateral.&lt;/strong&gt; Its "unexpected" is recombination from training data. Not a genuine leap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporal.&lt;/strong&gt; Doesn't see things age. Doesn't watch tech debt accumulate or teams change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First Principles.&lt;/strong&gt; Its "zero" is contaminated. When it "starts from scratch," it starts from the most common pattern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Counterfactual.&lt;/strong&gt; Can model scenarios. Can't &lt;em&gt;feel&lt;/em&gt; what it means to have chosen differently a year ago.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Seven anti-patterns
&lt;/h2&gt;

&lt;p&gt;Each one is the same mistake: delegating Claude Code's weakness without compensating for what it lacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. "Let something come to you."&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You want emergence. You get a generic response in inspirational language.&lt;br&gt;&lt;br&gt;
Instead: give material, say "find the pattern." Emergence is your job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. "Say something unexpected."&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You want lateral. You get a forced metaphor that goes nowhere.&lt;br&gt;&lt;br&gt;
Instead: give a role. &lt;em&gt;"Approach this as a biologist, not a programmer."&lt;/em&gt; Constraint frees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. "Start from zero."&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You want first principles. You get convention in a first-principles costume.&lt;br&gt;&lt;br&gt;
Instead: block explicitly. &lt;em&gt;"Don't use React. Don't use SPA. Don't use REST. What's left?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. "Which solution is best?"&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You want convergent. You get the first safe answer, not the best one.&lt;br&gt;&lt;br&gt;
Instead: two steps. &lt;em&gt;"Give me 8 approaches, including wild ones."&lt;/em&gt; Then: &lt;em&gt;"Now pick the best for my context."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. "Find problems with my idea."&lt;/strong&gt; (too early)&lt;br&gt;&lt;br&gt;
You want adversarial. You get fifteen problems, twelve academic.&lt;br&gt;&lt;br&gt;
Instead: develop first, &lt;em&gt;then&lt;/em&gt; attack. &lt;em&gt;"Now find the 3 most realistic risks."&lt;/em&gt; The number forces prioritization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. "Step 1: be creative."&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You want creativity. You get a brainstorm that reads like a tutorial.&lt;br&gt;&lt;br&gt;
Instead: &lt;em&gt;"Generate freely, no order"&lt;/em&gt; — then separately — &lt;em&gt;"now organize."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. "Will this scale?"&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You want temporal. You get "depends on use case."&lt;br&gt;&lt;br&gt;
Instead: give the future. &lt;em&gt;"Team grows from 3 to 12. Data goes 10x. Enterprise customers arrive. What fails first?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The formula is simple: Anti-pattern = delegating weakness without your input. Pattern = delegating strength + you covering the gap.&lt;/p&gt;
&lt;h2&gt;
  
  
  Thinking types chain into flows
&lt;/h2&gt;

&lt;p&gt;Nobody uses one type at a time. You chain them. Habitual sequences. I noticed four in my own work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug fix:&lt;/strong&gt; &lt;br&gt;
Abductive → Systems → Deductive → Sequential.&lt;br&gt;&lt;br&gt;
What could cause this? → trace dependencies → rule out → fix step by step.&lt;br&gt;&lt;br&gt;
Claude Code handles the whole route. Give it the bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture:&lt;/strong&gt; &lt;br&gt;
First Principles → Systems → Temporal → Adversarial → Spatial.&lt;br&gt;&lt;br&gt;
What's the core? → how does it connect? → how does it age? → where does it break? → draw it.&lt;br&gt;&lt;br&gt;
Shared. I bring temporal. Claude Code brings systems and diagrams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brainstorm:&lt;/strong&gt; &lt;br&gt;
Divergent → Analogical → Lateral → Emergent → Compression.&lt;br&gt;&lt;br&gt;
Generate → this reminds me of → what if totally different → something clicks → distill.&lt;br&gt;&lt;br&gt;
I'm stronger here. Claude Code brings volume. The click is mine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crisis:&lt;/strong&gt; &lt;br&gt;
Abductive → Deductive → Sequential → Adversarial.&lt;br&gt;&lt;br&gt;
Best guess → rule out → verify step by step → what else is burning?&lt;br&gt;&lt;br&gt;
Fully delegatable. Speed without panic.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;I built a diagnostic prompt. Paste it into Claude Code — or any AI with conversation history.&lt;/p&gt;

&lt;p&gt;If your AI has history with you, it will analyze how you've been thinking. Patterns you can't self-report. This gives the best result.&lt;/p&gt;

&lt;p&gt;If it's a fresh conversation, it walks you through five scenarios. No right answers. It watches &lt;em&gt;how&lt;/em&gt; you approach each one.&lt;/p&gt;

&lt;p&gt;What you get: your dominant types, your blind spots, your choreographies, and a custom instruction to give your AI — to compensate for what you tend to skip.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Click to copy the full diagnostic prompt
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# What's Your Thinking Style? — Cognitive Profile Diagnostic

You're about to profile my thinking style — not what I know, but how I think.
Use the framework below. Be warm and observational, like a coach reviewing
game tape — not a psychologist writing a diagnosis.

## The 18 Thinking Types

| # | Type | What it does | Example |
|---|------|-------------|---------|
| 1 | **Delta** | spots what changed vs. existing state | "what's new, what's reused, what's removed?" |
| 2 | **First Principles** | breaks down to atoms, rebuilds from zero | "forget how it works — what's the smallest truth?" |
| 3 | **Systems** | sees dependencies and feedback loops | "if we change X, what moves downstream?" |
| 4 | **Lateral** | arrives from where nobody expects | "what if we don't solve this problem at all?" |
| 5 | **Analogical** | understands new through familiar | "this is basically airport security for data" |
| 6 | **Divergent** | generates 20 options, quantity first | brainstorming — no filter, just volume |
| 7 | **Convergent** | narrows to one answer and justifies | decision — pick 1 from 20, explain why |
| 8 | **Sequential** | step by step, A→B→C | recipe, checklist, migration plan |
| 9 | **Abductive** | best explanation from incomplete data | "lawn is wet + car is wet → it probably rained" |
| 10 | **Emergent** | lets the pattern surface on its own | three unrelated things suddenly click into one |
| 11 | **Metacognitive** | thinking about thinking | "I'm being sequential but should switch to systems" |
| 12 | **Counterfactual** | changes history, not the question | "what if we'd chosen Postgres instead of Mongo?" |
| 13 | **Adversarial** | deliberately seeks failure | "what if the input is empty? what if the network drops?" |
| 14 | **Compression** | distills without losing the core | entire architecture in one sentence or metaphor |
| 15 | **Temporal** | thinks in time and scale | "this works for 50 users — what breaks at 5,000?" |
| 16 | **Inductive** | derives rules from examples | "every Friday deploy fails → Friday is the problem" |
| 17 | **Deductive** | derives conclusions from rules | "all GETs are public + this is GET → it's public" |
| 18 | **Spatial / Visual** | thinks in structures, maps, graphs | dependency graphs, flowcharts, mental maps |

## Organizing Axes

| Axis | Types |
|------|-------|
| **Directional** (breadth ↔ depth) | Divergent, Convergent |
| **Logical** (three forms of inference) | Deductive, Inductive, Abductive |
| **Structural** (how you see the problem) | Systems, Sequential, First Principles, Spatial |
| **Creative** (where the new comes from) | Lateral, Analogical, Emergent |
| **Meta** (thinking about thinking &amp;amp; change) | Metacognitive, Compression, Delta |
| **Protective** (what could go wrong) | Adversarial, Counterfactual, Temporal |

## What's a "Choreography"?

Nobody uses one type at a time. We chain them into flows — habitual sequences.

Examples:
- **Bug Fix:** Abductive → Systems → Deductive → Sequential
- **Architecture:** First Principles → Systems → Temporal → Adversarial
- **Brainstorm:** Divergent → Analogical → Lateral → Emergent → Compression

## What's a "Skin"?

A skin is a named operating mode — a stable bundle of choreography + attitude.

Examples:
- **The Architect**: Systems → Temporal → Adversarial → Spatial
- **The Operator**: Sequential → Deductive → Delta
- **The Poet**: Emergent → Compression → Lateral

---

## YOUR TASK

Profile my thinking style using the framework above. Work in three phases.

### Phase 1 — Retrospective (if you have history)

If you have access to our conversation history or memory — analyze it first.

Look for:
- Which thinking types I default to most often
- Which types I rarely or never use
- Recurring sequences (my choreographies)
- What triggers me to switch types
- Moments where my approach was unusual or surprising

If you have enough history, proceed to Phase 3.

### Phase 2 — Diagnostic Scenarios (if no or partial history)

Present these 5 scenarios ONE AT A TIME. Wait for my response before the next one.

**Scenario 1 — The Midnight Alert**
Your team's main product stops working at 11 PM. You have access to logs,
metrics, and the last 10 commits. What's your first move?

**Scenario 2 — The Blank Page**
You're starting a brand new project. No codebase, no constraints, just a goal.
How do you begin?

**Scenario 3 — The Stranger's Proposal**
A colleague proposes an approach you've never seen before. It sounds promising
but unfamiliar. What do you do?

**Scenario 4 — The Rewrite Question**
Should we rewrite the legacy module or keep patching it? You need an answer
by Friday. How do you think through this?

**Scenario 5 — The Retrospective**
A 3-month project just shipped. Your team lead asks for a short retrospective.
What do you focus on?

### Phase 3 — Thinking Style Profile

Produce my profile:

**1. Dominant Types** (top 3-5) — with specific evidence
**2. Blind Spots** (2-3) — what I might be missing
**3. My Choreographies** (2-3) — recurring sequences, named
**4. My Skins** (1-2) — default operating modes
**5. Complementary Prompt** — an instruction to give my AI to compensate:
"When I ask you to [X], also do [Y] — because I tend to skip [Z]."

Use a warm, observational tone — like a coach reviewing game tape.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd love to know
&lt;/h2&gt;

&lt;p&gt;This is one experiment. One conversation with one model.&lt;/p&gt;

&lt;p&gt;Does your AI give you the same strong/weak map? Or does it shift with the model, the context, the history?&lt;/p&gt;

&lt;p&gt;Do the anti-patterns land? Is "be creative" as useless for you as it was for me — or does it work somewhere I haven't looked?&lt;/p&gt;

&lt;p&gt;What did the diagnostic prompt tell you about yourself?&lt;/p&gt;

&lt;p&gt;If you try it, drop your dominant types in the comments. I'm genuinely curious whether patterns emerge across people — or whether each of us gets something entirely different.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm an IT analyst who works with Claude Code daily on &lt;a href="https://www.bestaiweb.ai" rel="noopener noreferrer"&gt;bestaiweb.ai&lt;/a&gt;. Not a cognitive scientist. Someone who's fascinated by how AI responds — and envious of the polymath-like breadth it has at its fingertips in a flash. So sometimes I stop building things and start exploring how to think with it instead. This is what I found. It might be wrong in places. But I love experimenting with AI about AI — and the best experiments are the ones you can't keep to yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>promptengineering</category>
    </item>
  </channel>
</rss>
