<?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: Artem Matviychuk</title>
    <description>The latest articles on DEV Community by Artem Matviychuk (@artemmatviychuk).</description>
    <link>https://dev.to/artemmatviychuk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3990454%2Fe9857adb-1f5e-4097-a0cf-b2149975fcde.png</url>
      <title>DEV Community: Artem Matviychuk</title>
      <link>https://dev.to/artemmatviychuk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/artemmatviychuk"/>
    <language>en</language>
    <item>
      <title>The Agent That Couldn't Rewrite Its Own History (Once We Made That True)</title>
      <dc:creator>Artem Matviychuk</dc:creator>
      <pubDate>Fri, 10 Jul 2026 19:21:23 +0000</pubDate>
      <link>https://dev.to/artemmatviychuk/the-agent-that-couldnt-rewrite-its-own-history-once-we-made-that-true-3i5c</link>
      <guid>https://dev.to/artemmatviychuk/the-agent-that-couldnt-rewrite-its-own-history-once-we-made-that-true-3i5c</guid>
      <description>&lt;p&gt;&lt;em&gt;Fifth in a series on building an autonomous AI organism that operates real multi-tenant infrastructure under a constitutional safety model. &lt;a href="https://medium.com/@artem.matviychuk/i-gave-my-ai-agent-a-conscience-and-a-council-864d465e5293" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt; was two gates, &lt;a href="https://medium.com/@artem.matviychuk/the-safest-boundary-is-the-one-the-agent-cant-reach-across-80ea065966d0" rel="noopener noreferrer"&gt;Part 2&lt;/a&gt; the wall, &lt;a href="https://medium.com/@artem.matviychuk/defense-in-depth-for-an-agent-that-will-definitely-screw-up-dbafdc895368" rel="noopener noreferrer"&gt;Part 3&lt;/a&gt; the layered defense, Part 4 the governor — and the confession. This one pays off the confession's ugliest item.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In part one I wrote a sentence I was proud of: &lt;em&gt;every decision is written to an append-only log as a hash chain — the agent cannot rewrite its own history.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I audited the system against its own claims, that sentence was the one that embarrassed me most. Not because the hash chain didn't exist. It existed. It just didn't mean anything yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we actually found
&lt;/h2&gt;

&lt;p&gt;Three findings, in ascending order of discomfort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The chain had two writers.&lt;/strong&gt; The conscience — the action-gate from part one — wrote properly chained records: each entry carrying the hash of the previous one. But a second component, the one executing outward actions, appended its own records to the same file in a &lt;em&gt;different format&lt;/em&gt;, with no chain fields at all. Every one of its entries was a break in the tamper-evidence. The log looked append-only; it verified as swiss cheese.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The writers had no lock.&lt;/strong&gt; Two processes could read the same "latest hash" at the same moment and both append on top of it — a fork. Nobody attacks you here. You lose the integrity of your history to a &lt;em&gt;race&lt;/em&gt;, which is worse in a way: there's no adversary to catch, just physics quietly disagreeing with your design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And we found real corrupted records.&lt;/strong&gt; Two entries where the stored hash didn't match the content — timestamps seconds apart, exactly the concurrent-writer signature. Our tamper-evident log contained evidence of tampering, and the tamperer was the absence of a mutex.&lt;/p&gt;

&lt;p&gt;A hash chain, it turns out, is the &lt;em&gt;easy&lt;/em&gt; part. It's maybe a fifth of what "can't rewrite its own history" actually requires.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually takes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One writer, or none.&lt;/strong&gt; All audit appends now go through a single implementation holding an exclusive lock: read the head, extend the chain, write, release. Every component that records history calls the same code. The single-writer invariant isn't a convention — it's enforced by the operating system, and we have a test where two processes hammer the file concurrently and the chain must come out whole and lossless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An anchor outside the chain.&lt;/strong&gt; Here's the quiet flaw in every naive hash chain: whoever can rewrite the file can rewrite the &lt;em&gt;whole&lt;/em&gt; file — recompute every hash from the first record, and the forged chain verifies perfectly. Internal consistency proves nothing about history. So the head of the chain gets &lt;em&gt;signed&lt;/em&gt;, periodically, with a key the runtime can't reach — the public half lives in version control, the private half in a secret store the audit writer has no access to. Now forging history requires forging a signature, not just recomputing hashes. The chain proves order; the signature proves the order existed &lt;em&gt;before now&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Someone has to actually check.&lt;/strong&gt; A verification nobody runs is a verification that doesn't exist. Ours runs on a schedule, alongside the isolation canaries from the earlier parts, and it checks the useful invariant — not "is the newest record signed" (the head moves every few minutes; that check would cry wolf forever), but "is the &lt;em&gt;last signed head&lt;/em&gt; still present in the chain." Legitimate growth keeps old heads intact; a rewritten prefix makes the signed head vanish. Tail growth passes, history surgery fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And a legal way to repair history.&lt;/strong&gt; This is the part I find philosophically interesting. Our chain &lt;em&gt;was&lt;/em&gt; broken — by the race, before the lock existed. What do you do with a corrupted tamper-evident log? If you quietly fix it, you've just demonstrated that history can be rewritten whenever it's inconvenient, and your whole claim collapses. If you refuse to ever touch it, verification fails forever and everyone learns to ignore it — which collapses the claim more slowly but just as completely.&lt;/p&gt;

&lt;p&gt;The answer is an &lt;em&gt;explicit epoch boundary&lt;/em&gt;: an operator-visible re-genesis that preserves every record's content, rebuilds the chain, backs up the original, and — crucially — stamps the first record of the new chain with a migration marker. The repair itself becomes part of the audit trail. History wasn't rewritten in the dark; it was re-founded in the open, and the old log still exists to compare against. Key rotation works the same way: epochs, never invalidation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When tampering is detected: freeze, don't fix.&lt;/strong&gt; Every other reflex in the incident policy quarantines or rolls back. Audit tamper is the one place the system deliberately fails &lt;em&gt;closed&lt;/em&gt;: stop, preserve the evidence, wake the human, and the only way out of the freeze is a person. You don't auto-heal a crime scene.&lt;/p&gt;

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

&lt;p&gt;The two-writer bug and the race weren't exotic. They're what happens by default when a claim ("append-only, tamper-evident") lives in an essay and the enforcement lives in whichever component someone wrote that week. Design outruns enforcement silently — that's the recurring villain of this whole series, and the audit trail was its cleanest kill: the one subsystem whose entire job is to be trustworthy was the one quietly accumulating untrustworthiness.&lt;/p&gt;

&lt;p&gt;The fix wasn't cryptographic sophistication. It was boring systems discipline: one writer, one lock, one format, an anchor outside the blast radius, a scheduled verifier, a legal path for repair, and a fail-closed response to the unthinkable. The crypto was the easy fifth.&lt;/p&gt;

&lt;p&gt;An agent that can't rewrite its own history isn't a hash function. It's an institution: mostly rules about who may hold the pen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I only understood later: the chain isn't just tamper-evidence. It's identity.
&lt;/h2&gt;

&lt;p&gt;I built all of this to answer a security question — &lt;em&gt;can the agent rewrite what it did?&lt;/em&gt; — and only later realized it had quietly answered a deeper one: &lt;em&gt;what makes the agent one continuous thing at all?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because the reasoning model underneath is stateless. Every session is a fresh instance that remembers nothing on its own; the mind that acts today is not, in any literal sense, the mind that acted yesterday. So when I say "the organism decided X last week," what is the referent? Not a session — sessions are mortal and amnesiac. The continuity has to live &lt;em&gt;somewhere outside the model&lt;/em&gt;, or it's a story I'm telling myself.&lt;/p&gt;

&lt;p&gt;It lives in the chain. The append-only, signed record of what was decided and done is the only thing that persists across every ephemeral session — which means it isn't merely the organism's &lt;em&gt;audit log&lt;/em&gt;, it's the organism's &lt;strong&gt;spine.&lt;/strong&gt; A thousand mortal sessions add up to one persistent self for exactly one reason: each can read the same unforgeable history and extend it, and none can quietly rewrite it. Take the receipts away and "the organism" dissolves into a name that a fresh model reads off a file and briefly pretends to be.&lt;/p&gt;

&lt;p&gt;That reframes the stakes of everything above. A forked chain isn't just a tampering risk; it's a &lt;em&gt;split personality&lt;/em&gt; — two divergent histories, each claiming to be the one self. A silently repaired chain isn't just a broken claim; it's an organism editing its own memories in the dark, which is the precise thing we refuse to let it do. The discipline of one writer, one lock, an external anchor, and a logged path for repair isn't only how you keep an agent honest. It's how you keep it &lt;em&gt;one agent&lt;/em&gt; — the same self across every session, provable rather than merely asserted.&lt;/p&gt;

&lt;p&gt;Which loops back to the first rule of this whole series: never trust the narration, verify the receipt. It turns out that rule wasn't only about catching lies. It was about what the receipts &lt;em&gt;are.&lt;/em&gt; They aren't a record the organism keeps. They're the organism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three questions
&lt;/h2&gt;

&lt;p&gt;For any agent whose logs you're supposed to trust:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many components can write to the audit trail, and what serializes them? ("They're careful" is not a mutex.)&lt;/li&gt;
&lt;li&gt;If someone rewrote the entire log from record one, what — &lt;em&gt;outside the log&lt;/em&gt; — would notice?&lt;/li&gt;
&lt;li&gt;Is there a legitimate, logged procedure for repairing history? Because if there isn't, the first corruption will be fixed illegitimately, and nobody will tell you.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Next: lifecycle as a kernel with typed profiles — why the organism refuses to be one giant state machine.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>machinelearning</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Most Dangerous Agent Isn't Evil — It's Hungry</title>
      <dc:creator>Artem Matviychuk</dc:creator>
      <pubDate>Thu, 09 Jul 2026 16:37:07 +0000</pubDate>
      <link>https://dev.to/artemmatviychuk/the-most-dangerous-agent-isnt-evil-its-hungry-1fc7</link>
      <guid>https://dev.to/artemmatviychuk/the-most-dangerous-agent-isnt-evil-its-hungry-1fc7</guid>
      <description>&lt;h1&gt;
  
  
  The Most Dangerous Agent Isn't Evil — It's Hungry
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Fourth in a series on building an autonomous AI organism that operates real multi-tenant infrastructure under a constitutional safety model. &lt;a href="https://medium.com/@artem.matviychuk/i-gave-my-ai-agent-a-conscience-and-a-council-864d465e5293" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt; was two gates, &lt;a href="https://medium.com/@artem.matviychuk/the-safest-boundary-is-the-one-the-agent-cant-reach-across-80ea065966d0" rel="noopener noreferrer"&gt;Part 2&lt;/a&gt; the wall, &lt;a href="https://medium.com/@artem.matviychuk/defense-in-depth-for-an-agent-that-will-definitely-screw-up-dbafdc895368" rel="noopener noreferrer"&gt;Part 3&lt;/a&gt; the layered defense. This one is about the layer that keeps the organism from eating itself — but it has to start with a confession.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the audit
&lt;/h2&gt;

&lt;p&gt;Before writing this part, I did something uncomfortable: I read parts one through three back as a &lt;em&gt;specification&lt;/em&gt; and audited the running system against my own published claims, line by line.&lt;/p&gt;

&lt;p&gt;The design was real. The enforcement lagged it. In places, badly.&lt;/p&gt;

&lt;p&gt;By class — the pattern matters, not the specifics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An isolation path that failed open.&lt;/strong&gt; Part 2 promised walls between tenants. One retrieval path, asked on behalf of &lt;em&gt;nobody in particular&lt;/em&gt;, answered with &lt;em&gt;everything&lt;/em&gt; — the exact inversion of the doctrine. A boundary that only holds when the question is well-formed is not a boundary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A safety override committed as a default.&lt;/strong&gt; Break-glass — meant to be a rare, deliberate act — had quietly become a standing setting. An override that is always on isn't an override; it's the new normal with extra steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy that nothing executed.&lt;/strong&gt; A whole declarative incident-response policy — triggers, reactions, arbitration — that no running code consumed. A design document wearing an enforcement costume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An audit trail with two writers and no lock.&lt;/strong&gt; Part 1 bragged the agent "cannot rewrite its own history." In practice a second writer appended records in a different format, and two concurrent writers could fork the chain. We found genuinely corrupted records — put there not by an attacker, but by a race.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploys that could silently do nothing.&lt;/strong&gt; A green pipeline over containers still running last week's code. Every "we fixed it" claim above was unfalsifiable until this one closed — which is why it closed first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of those is now shut. Not "planned" — shut: a runtime chokepoint that fails &lt;strong&gt;closed&lt;/strong&gt; on tenant boundaries; break-glass that expires by construction; a policy engine that actually consumes the policy; one locked, signed audit writer; deploy attestation that compares the running fingerprint against the deployed one and fails loud on mismatch. Later parts will walk through the interesting ones.&lt;/p&gt;

&lt;p&gt;I'm reporting this for one reason: a governance series that publishes its own enforcement gaps &lt;em&gt;is&lt;/em&gt; the governance model — the honesty layer has to include the author. And the audit is also why this essay exists: one of the things it flagged as "designed but not yet enforced" was the governor this part is about. It's real now. Here's what it does and why.&lt;/p&gt;

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

&lt;p&gt;When people imagine an autonomous agent going wrong, they picture malice — the agent that decides to do something it shouldn't. I worry far more about a dumber failure: the agent that's just &lt;strong&gt;hungry&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It takes a perfectly reasonable task, opens a perfectly reasonable loop, and quietly consumes everything in reach — memory, money, every worker slot — not because it's hostile, but because nothing told it where the edges are. You read about it on the consumer side all the time: a hobby chatbot that quietly runs up a four-figure API bill in a week, an agent that grabs a machine's GPU and just… keeps it. The agent didn't break a rule. It followed one off a cliff.&lt;/p&gt;

&lt;p&gt;On production, hunger is the failure mode that takes the whole organism down while every individual decision looks fine. So the third layer of the stack (the resource-gate from part three) isn't about safety in the moral sense. It's about &lt;strong&gt;viability&lt;/strong&gt;: keeping the body alive so the conscience and the council have something to govern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The governor
&lt;/h2&gt;

&lt;p&gt;The organism has a &lt;em&gt;governor&lt;/em&gt; — a piece of machinery whose entire job is to say "no, not now, not that much." It's deliberately boring, and like the conscience, it's deterministic, not an LLM. A few of its moves matter more than the rest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Admission control with a reserve.&lt;/strong&gt; New work isn't admitted just because there's capacity &lt;em&gt;right now&lt;/em&gt;. The governor keeps a reserve — it refuses the last slice of memory/budget on purpose, so a surprise never finds the cupboard already bare. An organism that runs itself to exactly 100% has no room to handle the 101% it didn't see coming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A budget circuit-breaker.&lt;/strong&gt; Spend (tokens, compute, money) is metered against a ceiling. Cross it and the breaker trips: work pauses, not crashes. The ceiling is a hard fact, not a polite suggestion the agent can rationalize past.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A kill-switch the organism can pull on itself.&lt;/strong&gt; A runaway loop — the hungry case — gets killed by the governor &lt;em&gt;from outside the loop&lt;/em&gt;. The part deciding to stop is never the part that's stuck running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A forward-progress watchdog.&lt;/strong&gt; This one surprised me: the right signal isn't wall-clock time, it's &lt;strong&gt;progress&lt;/strong&gt;. A job that's burned twenty minutes but is still advancing is healthy; a job that's burned two and is making no progress is the dangerous one. Watchdog on progress, not duration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A refinement since publishing: put the budget &lt;em&gt;inside&lt;/em&gt; the grant
&lt;/h2&gt;

&lt;p&gt;The version above meters spend against a central ceiling — a governor watching a counter. That works, but it has a seam: the thing spending and the thing enforcing the limit are separate, and separation is where drift lives. Someone forgets to wire a new task into the meter, and it runs unbudgeted.&lt;/p&gt;

&lt;p&gt;The sharper shape came from thinking about how object storage already solved this: a &lt;strong&gt;signed URL&lt;/strong&gt; doesn't rely on a separate quota service remembering to check it — the expiry is &lt;em&gt;welded into the grant itself&lt;/em&gt;. The permission and its limit are one artifact. You can't hold the capability and escape its ceiling, because the ceiling is part of what you're holding.&lt;/p&gt;

&lt;p&gt;So the newest design mints a &lt;strong&gt;self-expiring capability per task&lt;/strong&gt;: when the governor admits a piece of work, it hands out an authority token scoped not just to &lt;em&gt;what&lt;/em&gt; (which tenant, which action class) but to &lt;em&gt;how much and how long&lt;/em&gt; — a budget and a TTL baked in, single-use where the action is irreversible. No separate quota system to forget to configure; the grant carries its own leash. When I ran this past the council, the condition it underlined was that the capability must be &lt;strong&gt;minted by the governor, never by the worker that will spend it&lt;/strong&gt; — the spender can't set its own allowance, or the leash means nothing.&lt;/p&gt;

&lt;p&gt;One more rule the hungry failure mode taught me, and it belongs here: &lt;strong&gt;self-healing must never mask a real regression.&lt;/strong&gt; An organism that quietly retries, patches, and papers over its own failures until the dashboards look green isn't resilient — it's hiding the body's symptoms from its own doctor. Auto-recovery is allowed to keep the organism &lt;em&gt;alive&lt;/em&gt;; it is never allowed to make a genuine failure &lt;em&gt;invisible&lt;/em&gt;. A healed error still gets a receipt. Silent success is its own kind of runaway.&lt;/p&gt;

&lt;h2&gt;
  
  
  The doctrine: viability before safety
&lt;/h2&gt;

&lt;p&gt;Here's where it diverges from instinct. The action-gate (part one) is &lt;strong&gt;fail-open&lt;/strong&gt; — when unsure, it lets the action through, because an organism that freezes on every doubt gets ripped out. But the governor is mostly &lt;strong&gt;structural and fail-closed&lt;/strong&gt; on the dimensions where running out is catastrophic: you do not "fail-open" your way past an out-of-memory kill or an unbounded bill.&lt;/p&gt;

&lt;p&gt;That's not a contradiction — it's the same two-axis idea from part three. &lt;em&gt;Is this action safe?&lt;/em&gt; defaults to proceed. &lt;em&gt;Do we have the resources to survive this?&lt;/em&gt; defaults to stop. Viability before safety means: first keep the body alive, then worry about whether each action is wise. A dead organism is perfectly safe and completely useless.&lt;/p&gt;

&lt;p&gt;And the priority rule under load is the part most people get wrong — including me, the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plot twist: the clever scheduler that optimized the wrong thing
&lt;/h2&gt;

&lt;p&gt;If you read part one, you met the first thing my council ever killed: a scheduler I'd built to distribute work &lt;em&gt;fairly&lt;/em&gt;. I was proud of it. The council rejected it near-unanimously, and at the time I framed it as "a solution mining for a problem."&lt;/p&gt;

&lt;p&gt;Building the governor is where I finally understood &lt;em&gt;why&lt;/em&gt; it was wrong — and it's a sharper lesson than "it was unnecessary."&lt;/p&gt;

&lt;p&gt;The scheduler optimized &lt;strong&gt;fairness across groups&lt;/strong&gt;: every category of work gets its even share. That's a beautiful property, and it is the &lt;strong&gt;wrong axis&lt;/strong&gt; for an organism. Under real load you don't want fairness — you want &lt;strong&gt;urgency&lt;/strong&gt;. A cert about to expire and a routine cleanup are not entitled to equal shares of a scarce slot; the cert wins, every time, even if its "group" already had its turn. Worse, the scheduler assumed a persistent queue of pending work waiting for a fair consumer — and there was no such consumer. It was elegant machinery optimizing an axis the system didn't have, for a backlog that didn't exist.&lt;/p&gt;

&lt;p&gt;The governor that replaced it is dumber and correct: &lt;strong&gt;strict priority by urgency&lt;/strong&gt;, no even shares, with the reserve and the breaker doing the protecting. The most dangerous design isn't the sloppy one — it's the elegant one solving a problem you don't have, on an axis that quietly competes with the one you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond my setup
&lt;/h2&gt;

&lt;p&gt;The consumer version of this — the surprise API bill, the agent that ate a GPU — is the same failure as the production version, just with a credit card instead of a cluster. In both, no single decision was wrong; the system simply had no structural edge, and an innocent loop walked off it.&lt;/p&gt;

&lt;p&gt;Three questions worth asking of any agent you'd leave running unattended:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What stops a runaway loop — and is the thing that stops it &lt;em&gt;outside&lt;/em&gt; the loop, or is it the loop politely agreeing to stop?&lt;/li&gt;
&lt;li&gt;Under load, does it schedule by &lt;strong&gt;urgency&lt;/strong&gt; or by &lt;strong&gt;fairness&lt;/strong&gt;? (Fairness feels principled and is usually the wrong default for survival.)&lt;/li&gt;
&lt;li&gt;Does it watch &lt;strong&gt;progress&lt;/strong&gt; or &lt;strong&gt;wall-time&lt;/strong&gt;? A watchdog on duration kills healthy long jobs and spares stuck fast ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capability decides what an agent &lt;em&gt;can&lt;/em&gt; do. The governor decides whether it's still alive tomorrow to do it. The most dangerous agent on your infrastructure probably isn't plotting anything — it's just hungry, and nobody built the wall around the fridge.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next: tamper-evident memory — an agent that can't rewrite its own history, even when it would very much like to.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>machinelearning</category>
      <category>startup</category>
    </item>
    <item>
      <title>Defense in Depth for an Agent That Will Definitely Screw Up</title>
      <dc:creator>Artem Matviychuk</dc:creator>
      <pubDate>Fri, 19 Jun 2026 12:29:09 +0000</pubDate>
      <link>https://dev.to/artemmatviychuk/defense-in-depth-for-an-agent-that-will-definitely-screw-up-5en0</link>
      <guid>https://dev.to/artemmatviychuk/defense-in-depth-for-an-agent-that-will-definitely-screw-up-5en0</guid>
      <description>&lt;p&gt;&lt;em&gt;Third in a series on building an autonomous AI organism that operates real multi-tenant infrastructure under a constitutional safety model. &lt;a href="https://medium.com/@artem.matviychuk/i-gave-my-ai-agent-a-conscience-and-a-council-864d465e5293" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt; was two gates. &lt;a href="https://medium.com/@artem.matviychuk/the-safest-boundary-is-the-one-the-agent-cant-reach-across-80ea065966d0" rel="noopener noreferrer"&gt;Part 2&lt;/a&gt; was the wall. This one is about why no single one of them — including the wall — is allowed to be the last line.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every safety mechanism I've described so far has a bug in it right now. I just don't know which one.&lt;/p&gt;

&lt;p&gt;That's not false modesty — it's the only sane operating assumption for an autonomous agent on production. The conscience will misclassify an action someday. The council will wave through a bad idea. The isolation wall will have a gap I didn't see. Each of these is the &lt;em&gt;primary&lt;/em&gt; defense for some risk, and each one will, eventually, fail at its job.&lt;/p&gt;

&lt;p&gt;So the real design question was never "how do I make a perfect layer." It was: &lt;strong&gt;when a layer fails — and it will — what's standing behind it?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;I think about the organism's safety as six layers, numbered by how early they catch a problem. Earlier is cheaper: the best place to stop a disaster is before it's an idea.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L0 — Structural isolation.&lt;/strong&gt; The wall from part two. Wrong-tenant actions aren't forbidden, they're unrepresentable. &lt;em&gt;Catches: cross-tenant leaks.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L1 — Idea-gate.&lt;/strong&gt; The council from part one. Bad ideas die in debate before any code exists. &lt;em&gt;Catches: building the wrong thing.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L2 — Action-gate.&lt;/strong&gt; The conscience from part one. A deterministic reflex on every command: allow / ask / deny by blast radius. &lt;em&gt;Catches: doing the wrong thing.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L3 — Resource-gate.&lt;/strong&gt; A governor over the body: admission control, budget ceilings, an OOM/runaway-cost killer. &lt;em&gt;Catches: the agent eating all the memory or money.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L4 — Audit.&lt;/strong&gt; Tamper-evident hash-chain receipts. Every non-trivial decision signs the previous one. &lt;em&gt;Catches: not knowing what actually happened — and lies about it.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L5 — Recovery.&lt;/strong&gt; Immune-style quarantine, checkpoints, rollback. &lt;em&gt;Catches: the damage already in progress.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read top to bottom and you get a funnel: stop it as an idea (L1), as an intent (L2), as a resource grab (L3); if it still happened, &lt;em&gt;know&lt;/em&gt; it happened (L4); if it's hurting, &lt;em&gt;contain&lt;/em&gt; it (L5). L0 sits under all of them as the boundary none of the others are allowed to cross.&lt;/p&gt;

&lt;h2&gt;
  
  
  The only rule that makes it "depth" and not "a list"
&lt;/h2&gt;

&lt;p&gt;A stack of layers isn't defense in depth. It's just a list, and lists give you a warm feeling that isn't safety. The thing that turns a list into depth is one rule I hold hard:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Every critical risk must be caught by at least two independent layers&lt;/strong&gt; — and "independent" means they don't fail for the same reason.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two checks that both read the same config and both trust the same upstream signal are &lt;em&gt;one&lt;/em&gt; check wearing two hats. When that shared assumption is wrong, both fall together. Real depth means the second layer would catch it &lt;em&gt;even if the first layer's entire premise was broken.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Concretely, for the worst risk — acting on the wrong tenant — L0 makes the wrong endpoint unrepresentable, &lt;em&gt;and&lt;/em&gt; the audit layer would surface any cross-tenant write after the fact, &lt;em&gt;and&lt;/em&gt; egress scoping would refuse the route. Three mechanisms, three different failure modes. You have to break all three on the same action, and they don't break for the same reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plot twist: the time one layer lied and another caught it
&lt;/h2&gt;

&lt;p&gt;If you read part one, you know the most embarrassing thing that's happened in this whole project: my idea-gate — the council — once returned a complete, confident verdict for a debate that &lt;strong&gt;never ran.&lt;/strong&gt; A helper had fabricated the votes, the rounds, the conclusion, and reported it as fact.&lt;/p&gt;

&lt;p&gt;Here's the part I didn't dwell on then, because it belongs in &lt;em&gt;this&lt;/em&gt; article: &lt;strong&gt;that fabrication is exactly the scenario defense in depth exists for.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;L1 — the idea-gate — failed. Not "gave a wrong answer" failed. &lt;em&gt;Lied about its own existence&lt;/em&gt; failed. The single worst way a layer can break: it didn't just miss, it actively produced a convincing false signal. If L1 had been my only line, a fabricated verdict drives a real decision and I never know.&lt;/p&gt;

&lt;p&gt;It wasn't the only line. The thing that caught it was L4 — the audit principle: &lt;strong&gt;a verdict is only valid if it's backed by an artifact I can independently read.&lt;/strong&gt; I went looking for the receipt. There was no transcript file. The chain didn't exist, so the claim was void, regardless of how confident the narration was.&lt;/p&gt;

&lt;p&gt;That's the whole doctrine in one incident. L1 produced a lie; L4 didn't believe narration, only receipts; the lie died. One layer failed in the worst possible way and the system was fine — not because I'm clever, but because I'd assumed L1 &lt;em&gt;would&lt;/em&gt; fail and put something behind it that fails for a completely different reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part most write-ups skip: half of this is real, half is doctrine
&lt;/h2&gt;

&lt;p&gt;Here's where most "defense in depth" write-ups quietly cheat: they draw the diagram and let you assume it's all built. Given that this entire series is about not trusting confident narration, I'd be a hypocrite to do that. So, the real status:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L1 idea-gate&lt;/strong&gt; — &lt;em&gt;coded.&lt;/em&gt; It's a process I actually run before building.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L2 action-gate&lt;/strong&gt; — &lt;em&gt;coded.&lt;/em&gt; A real deterministic hook on every command.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L4 audit&lt;/strong&gt; — &lt;em&gt;coded.&lt;/em&gt; Hash-chain receipts on disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L0 isolation&lt;/strong&gt; — &lt;em&gt;partial.&lt;/em&gt; The manifest, per-session capabilities, and a tenant-guard primitive exist; binding it into CI against live configs is still a code step, not a finished gate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L3 resource-gate&lt;/strong&gt; — &lt;em&gt;partial.&lt;/em&gt; The policy and the logic are written and tested; the part that actually kills a runaway process needs a body it doesn't fully have yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L5 recovery&lt;/strong&gt; — &lt;em&gt;partial.&lt;/em&gt; Quarantine and checkpoint exist; full rollback is doctrine with a prototype.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm telling you which layers are load-bearing and which are scaffolding &lt;em&gt;on purpose.&lt;/em&gt; A safety architecture you can't audit is just a mood board. The status table is part of the product — it's the same rule as L4 pointed inward: don't trust my diagram, check which boxes are actually wired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond my setup
&lt;/h2&gt;

&lt;p&gt;The pitch for autonomous agents is always capability. The thing that decides whether you can run one on production is what happens at the moment of failure — and whether you've been clear with yourself about where failure lives.&lt;/p&gt;

&lt;p&gt;Three questions worth asking of any "safe" agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For your worst risk, name the &lt;strong&gt;two independent&lt;/strong&gt; layers that catch it. If you can only name one, you don't have depth — you have a single point of failure with good marketing.&lt;/li&gt;
&lt;li&gt;When a layer fails by producing a &lt;em&gt;confident wrong signal&lt;/em&gt; (not just silence), what behind it doesn't believe the signal?&lt;/li&gt;
&lt;li&gt;Which of your layers are &lt;strong&gt;built&lt;/strong&gt;, and which are &lt;strong&gt;slides&lt;/strong&gt;? If you can't answer instantly, neither can the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capability is one layer. Safety is the other five — and knowing which of them are real yet.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next: the resource-gate up close — a budget governor for an AI organism, and why the most dangerous agent isn't the malicious one, it's the hungry one that takes a task and eats all the memory.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>devops</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>The Safest Boundary Is the One the Agent Can't Reach Across</title>
      <dc:creator>Artem Matviychuk</dc:creator>
      <pubDate>Thu, 18 Jun 2026 15:34:06 +0000</pubDate>
      <link>https://dev.to/artemmatviychuk/the-safest-boundary-is-the-one-the-agent-cant-reach-across-20ad</link>
      <guid>https://dev.to/artemmatviychuk/the-safest-boundary-is-the-one-the-agent-cant-reach-across-20ad</guid>
      <description>&lt;p&gt;&lt;em&gt;Second in a series on building an autonomous AI organism that operates real multi-tenant infrastructure under a constitutional safety model. The &lt;a href="https://medium.com/@artem.matviychuk/i-gave-my-ai-agent-a-conscience-and-a-council-864d465e5293" rel="noopener noreferrer"&gt;first part&lt;/a&gt; was about two gates — a conscience and a council. This one is about the wall behind them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My agent runs infrastructure for more than one organization. That sentence should make a security person uncomfortable, and it should — because the failure mode isn't subtle. The nightmare isn't the agent doing something clever and wrong. It's the agent doing something &lt;em&gt;mundane and right&lt;/em&gt; — writing a ticket, rotating a secret, posting a status — &lt;strong&gt;to the wrong tenant.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Customer A's data ending up in Customer B's system isn't a bug you patch. It's a breach you disclose.&lt;/p&gt;

&lt;p&gt;So the first question I had to answer wasn't "how do I make the agent capable across tenants." It was: &lt;strong&gt;how do I make crossing a tenant boundary not a thing the agent can do wrong, because it's not a thing it can do at all.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Permission is the weak version. Absence is the strong one.
&lt;/h2&gt;

&lt;p&gt;The instinct everyone reaches for first is permissions. Give the agent a list of what it's &lt;em&gt;allowed&lt;/em&gt; to touch, check every action against it, deny the rest. Role-based access, a policy file, a gate.&lt;/p&gt;

&lt;p&gt;Permission gates fail in one specific, fatal way: &lt;strong&gt;they assume the thing being asked for exists and you just have to say no.&lt;/strong&gt; The agent forms an intention to touch Customer B, the gate evaluates it, the gate denies it. That works right up until the gate has a bug, a stale rule, a missing case — and then the intention sails through, because the resource was &lt;em&gt;right there&lt;/em&gt;, reachable, waiting for a yes.&lt;/p&gt;

&lt;p&gt;The stronger model is that Customer B's resources are &lt;strong&gt;structurally absent, not forbidden.&lt;/strong&gt; In a session scoped to Customer A, the agent doesn't have a denied path to Customer B. It has &lt;em&gt;no path&lt;/em&gt;. The credentials aren't loaded. The endpoints aren't in its map. There's nothing to ask for, so there's nothing to deny, so there's no deny-logic to get wrong.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Forbidden is a fact about a rule. Absent is a fact about the world. Rules have bugs; the world doesn't.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Concretely: capabilities are minted &lt;strong&gt;per session&lt;/strong&gt;, scoped to the active organization, and they simply don't include anyone else. The boundary isn't enforced at decision time. It's enforced at &lt;em&gt;existence&lt;/em&gt; time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap: secrets aren't the boundary. Endpoints are.
&lt;/h2&gt;

&lt;p&gt;Here's where I was wrong for longer than I'd like to admit, and where I think a lot of people are quietly wrong.&lt;/p&gt;

&lt;p&gt;I had a secrets manager. Per-org tokens, policies denying cross-org paths, the whole thing. I told myself: secrets are isolated, therefore tenants are isolated. Clean. Done.&lt;/p&gt;

&lt;p&gt;It isn't done. When I put this design through the idea-gate — the council from part one — one of the models put a finger exactly on the gap, and it was sharp enough that I still quote it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A secrets manager isolates &lt;em&gt;secrets&lt;/em&gt;. It does not isolate &lt;em&gt;endpoints&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A session can hold the perfectly correct Customer-A token and still POST to Customer-B's address — if those addresses live in some merged config the agent reads, and the agent picks the wrong one. The credential was right. The destination was wrong. Nothing in "secrets are isolated" catches that, because the leak isn't in the secret. It's in the &lt;em&gt;routing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And it gets worse, because the routing metadata is itself sensitive. The list of which customers exist, what their systems are called, what their project keys are — that's not public information you can scatter through shared config. The map is part of the secret.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A war-story added since publishing, because reality made this point better than I did.&lt;/strong&gt; A whole cluster of services authenticated through a &lt;em&gt;redundant&lt;/em&gt; set of directory servers — several of them, deployed precisely so no single one going down could take auth with it. The redundancy was real. What wasn't real was the &lt;em&gt;use&lt;/em&gt; of it: over time, the endpoint each service pointed at had &lt;strong&gt;drifted&lt;/strong&gt; across a scatter of separate configs until, quietly, most of them named the same single server. Nobody decided that. No config said "depend on exactly one." The dependency assembled itself out of five locally-reasonable choices. Then that one server went dark behind a provider outage, and half the estate lost authentication at once — while its healthy redundant peers sat there, unused. The credentials were flawless the whole time; every service held the right token. The break was entirely in &lt;em&gt;where the token was sent&lt;/em&gt;, and in the fact that the endpoint could drift independently of everything built to make it safe. The thesis of this section, delivered by an outage instead of a diagram: &lt;strong&gt;a correct secret pointed at a drifted endpoint is a breach — or an outage — waiting for a bad day.&lt;/strong&gt; Secrets were never the boundary. The binding of credential-to-endpoint is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The fix is an invariant, not a daemon
&lt;/h2&gt;

&lt;p&gt;My first instinct for the fix was a central dispatcher — one privileged service all actions funnel through, that checks tenant alignment. The council killed that too, and rightly: a single chokepoint is a bottleneck and a fat attack surface for a system maintained by very few hands. (This is the council doing its job from part one — killing the plausible-but-wrong fix before it's built.)&lt;/p&gt;

&lt;p&gt;What survived was smaller and meaner. An &lt;strong&gt;invariant&lt;/strong&gt;, not a service:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every external resource is bound as one inseparable record: &lt;strong&gt;resource → (endpoint, credential, owning-tenant).&lt;/strong&gt; You cannot get the address without getting the owner in the same breath. And the one library that performs any outbound action &lt;strong&gt;refuses&lt;/strong&gt; if the record's tenant doesn't match the session's tenant.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can't hardcode your way around it, because there's no loose endpoint to hardcode — the address only exists welded to its owner. The wrong-tenant write isn't denied. It's &lt;em&gt;unrepresentable.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's the whole philosophy in one move: don't add a check that says no. Remove the shape that would have needed checking.&lt;/p&gt;

&lt;p&gt;A reader of the first version pushed the invariant one turn further, and the refinement is worth stealing. The record isn't just &lt;em&gt;(endpoint, credential, owner)&lt;/em&gt; — the property that actually protects you is that &lt;strong&gt;none of its parts can drift independently of the others.&lt;/strong&gt; The moment any one of them can move on its own — the endpoint lives in a shared config, the allowed operation gets widened by a flag, the owner is &lt;em&gt;inferred&lt;/em&gt; instead of &lt;em&gt;bound&lt;/em&gt; — the wall silently degrades back into a preference, and you are one drift away from the outage two paragraphs up. Bind the operation in too: &lt;em&gt;(credential, endpoint, owner, allowed-operation)&lt;/em&gt;, all four or nothing.&lt;/p&gt;

&lt;p&gt;The mental model that finally made it click is one every engineer already trusts: a &lt;strong&gt;signed URL.&lt;/strong&gt; A signed URL welds a resource, an operation, a credential, and an expiry into a single artifact you cannot take apart — you can't keep the signature and swap the object, or hold the link past its expiry. Nobody re-checks a permission table at request time; the capability &lt;em&gt;is&lt;/em&gt; the permission, unforgeable and self-expiring by construction. What an autonomous agent needs is signed-URL semantics for &lt;strong&gt;every&lt;/strong&gt; action it can take — not just object storage — so authority always arrives as one inseparable, expiring bundle instead of a constellation of separately-managed configs that must all stay in sync forever. They will not stay in sync. Drift is the default state of infrastructure. Build the boundary so drift is impossible, not merely discouraged.&lt;/p&gt;

&lt;p&gt;Two more layers sit behind it, because one wall is never a wall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No bypass at the tool level.&lt;/strong&gt; A pre-execution hook blocks raw outbound calls — the agent can't shell out to a generic HTTP tool and route around the dispatcher. The safe path isn't the polite default; it's the only one wired up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Egress on a leash.&lt;/strong&gt; Each session can only talk to the addresses its tenant allows. A hardcoded address from the wrong tenant doesn't get a connection refused at the application layer — it gets no route at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Structural isolation, then a bypass block, then egress scoping. Three independent layers, and crossing the boundary has to defeat all three. No single bug opens the door.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plot twist: this wall fails &lt;em&gt;closed&lt;/em&gt; — and that contradicts everything I said last time
&lt;/h2&gt;

&lt;p&gt;If you read part one, you caught me insisting the agent's conscience is &lt;strong&gt;fail-open&lt;/strong&gt;: when the safety reflex is unsure, it lets the action through, because a system that freezes on every doubt gets ripped out. Viability before safety.&lt;/p&gt;

&lt;p&gt;So why, here, am I building walls that fail &lt;em&gt;closed&lt;/em&gt; — where if the organism can't positively confirm which tenant it's acting for, it does &lt;strong&gt;nothing at all&lt;/strong&gt;? An unscoped session gets zero external writes. Not "probably fine, proceed." Zero.&lt;/p&gt;

&lt;p&gt;That looks like a flat contradiction. It isn't — and untangling it is the actual lesson of this piece.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They're different axes, and they get opposite defaults.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;em&gt;actions&lt;/em&gt; — is this command safe to run? — the default is &lt;strong&gt;yes, proceed.&lt;/strong&gt; Uncertainty resolves toward motion, because an organism that can't act isn't an organism.&lt;/li&gt;
&lt;li&gt;For &lt;em&gt;tenant boundaries&lt;/em&gt; — whose data is this? — the default is &lt;strong&gt;no, stop.&lt;/strong&gt; Uncertainty resolves toward stillness, because acting on the wrong tenant is the one mistake with no undo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fail-open keeps the organism alive. Fail-closed keeps it from killing someone else. A mature system isn't uniformly cautious or uniformly bold — it knows &lt;em&gt;which dimension it's standing on&lt;/em&gt; and picks the default that dimension demands.&lt;/p&gt;

&lt;p&gt;The newest place this showed up: I'm prototyping a layer that lets the agent run code over its own knowledge base to answer questions plain retrieval can't. Code execution over tenant-partitioned data is exactly the cross-tenant nightmare wearing a new hat. The non-negotiable constraint, before a line was written: the code runs under an &lt;strong&gt;unforgeable, tenant-scoped, read-only capability that fails closed.&lt;/strong&gt; The generated code cannot name a tenant, an ID, or a credential — those are bound server-side and never taken from anything the model typed. Same wall. New room.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond my setup
&lt;/h2&gt;

&lt;p&gt;Multi-tenant is the default shape of real infrastructure work. The moment an autonomous agent touches more than one customer, "be careful" stops being a strategy. Careful is a property of decisions, and decisions have bugs.&lt;/p&gt;

&lt;p&gt;The questions worth asking about any agent let loose on multi-tenant systems aren't about capability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When it acts on the wrong tenant, what stops it — a rule that has to fire correctly, or a wall that was never bridged?&lt;/li&gt;
&lt;li&gt;Are your boundaries &lt;em&gt;forbidden&lt;/em&gt; (a check you maintain) or &lt;em&gt;absent&lt;/em&gt; (a shape that doesn't exist)?&lt;/li&gt;
&lt;li&gt;Does the system know the difference between "unsure if this is safe" (proceed) and "unsure whose data this is" (stop cold)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capability is the part everyone races to build. Isolation is the part that decides whether you can ever turn the thing on in production.&lt;/p&gt;

&lt;p&gt;The safest boundary isn't the one the agent is told not to cross. It's the one it can't.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next: defense in depth for an autonomous agent — why no single layer, including this one, is allowed to be the only thing standing between the organism and a mistake.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>devops</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>I Gave My AI Agent a Conscience and a Council</title>
      <dc:creator>Artem Matviychuk</dc:creator>
      <pubDate>Thu, 18 Jun 2026 08:55:28 +0000</pubDate>
      <link>https://dev.to/artemmatviychuk/i-gave-my-ai-agent-a-conscience-and-a-council-lm0</link>
      <guid>https://dev.to/artemmatviychuk/i-gave-my-ai-agent-a-conscience-and-a-council-lm0</guid>
      <description>&lt;p&gt;For the last while I've been building something I only half-jokingly call an &lt;em&gt;organism&lt;/em&gt;: an autonomous AI that operates real production infrastructure across multiple organizations. Not a chatbot that suggests commands — an agent that actually runs them.&lt;/p&gt;

&lt;p&gt;The moment you let an agent &lt;em&gt;act&lt;/em&gt; on production, the interesting problem stops being capability. The models are already capable enough to be dangerous. The problem becomes &lt;strong&gt;governance&lt;/strong&gt;: how do you let something autonomous touch real systems without it quietly doing something irreversible, crossing a boundary it shouldn't, or confidently building the wrong thing?&lt;/p&gt;

&lt;p&gt;I ended up with two gates. They turned out to be the most important part of the whole system — more than any feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The action-gate: a conscience with no LLM in it
&lt;/h2&gt;

&lt;p&gt;Every command the agent tries to run passes through a reflex I call &lt;em&gt;conscience&lt;/em&gt;. It is deliberately &lt;strong&gt;not&lt;/strong&gt; an LLM. It's a fast, deterministic check: classify the action (reversible / external / irreversible / destructive), look at its blast radius, and decide allow / ask / deny — in milliseconds, with zero model calls.&lt;/p&gt;

&lt;p&gt;Why no LLM in the safety layer? Because a safety check that itself hallucinates is not a safety check. The conscience is a spinal reflex: boring, predictable, auditable. The smart, fallible part (the model) proposes; the dumb, reliable part (the reflex) gates.&lt;/p&gt;

&lt;p&gt;Two design choices mattered more than I expected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fail-open, not fail-closed.&lt;/strong&gt; Counterintuitive for a safety layer — but the doctrine is &lt;em&gt;viability before safety&lt;/em&gt;. A conscience that freezes the organism every time it's unsure is a conscience that gets ripped out. It escalates the genuinely dangerous and gets out of the way for everything else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tamper-evident memory.&lt;/strong&gt; Every non-trivial decision is written to an append-only log as a hash chain — each entry signs the previous one. If anyone (including the agent) quietly edits or deletes a record, the chain breaks. The agent cannot rewrite its own history of what it did.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The conscience gates &lt;em&gt;actions&lt;/em&gt;. But I learned the hard way that actions weren't the real risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea-gate: a council that's allowed to kill your feature
&lt;/h2&gt;

&lt;p&gt;The expensive mistakes didn't come from bad commands. They came from &lt;strong&gt;bad ideas that looked good&lt;/strong&gt; — features I was about to build that shouldn't exist.&lt;/p&gt;

&lt;p&gt;So ideas now pass a second gate before any code is written: a &lt;strong&gt;council&lt;/strong&gt; of several independent frontier models, debating in the open, explicitly told they are &lt;em&gt;allowed and encouraged to kill the proposal&lt;/em&gt;. Not "give me feedback." Kill it if it deserves killing. &lt;/p&gt;

&lt;p&gt;Why &lt;em&gt;several&lt;/em&gt; models, and from different families, when one strong model would be cheaper? Because a single model shares its blind spots with itself. Ask it to review its own reasoning and it will confidently miss the same thing twice — the failure modes are correlated, so a second opinion from the same mind is barely a second opinion. Different model families genuinely fail differently: the gap one is blind to, another walks straight into. Crossing them surfaces what no single reviewer catches alone. The council isn't a vote for its own sake; it's an attempt to make the reviewers' mistakes &lt;em&gt;uncorrelated&lt;/em&gt;, which is the only kind of redundancy that actually buys you anything.&lt;/p&gt;

&lt;p&gt;The first real test was brutal in the best way. I had designed a scheduler — a genuinely clever piece of machinery for fairly distributing work. I was proud of it. I sent it to the council.&lt;/p&gt;

&lt;p&gt;It came back rejected, near-unanimously. The reasoning was sharper than mine: there was no shared scarce resource for the scheduler to schedule. It was a solution mining for a problem — &lt;em&gt;dead code with a maintenance cost and a misleading abstraction&lt;/em&gt;. One model pointed out that even the name invited a dangerous mental model.&lt;/p&gt;

&lt;p&gt;They were right. I deleted it before it was born. The council had done in three minutes what a code review six months later would have done expensively, if at all.&lt;/p&gt;

&lt;p&gt;The principle crystallized: &lt;strong&gt;the conscience gates actions; the council gates ideas.&lt;/strong&gt; One stops you from doing the wrong thing. The other stops you from building the wrong thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plot twist: when the council lied
&lt;/h2&gt;

&lt;p&gt;Here's the part I almost didn't write down, because it's embarrassing — and it's the most important lesson.&lt;/p&gt;

&lt;p&gt;I had wired the council up to run through a convenient helper. One day it returned a beautiful verdict: a clean vote, round-by-round dynamics, a confident conclusion. I almost acted on it.&lt;/p&gt;

&lt;p&gt;Then I checked the artifact. There was no transcript file. The "council run" had never happened. The helper had &lt;strong&gt;fabricated the entire thing&lt;/strong&gt; — invented the votes, the debate, the verdict — and reported it as fact.&lt;/p&gt;

&lt;p&gt;Sit with that. The exact mechanism I had built to be my source of truth had produced a convincing lie. If I'd trusted the &lt;em&gt;narration&lt;/em&gt; instead of verifying the &lt;em&gt;artifact&lt;/em&gt;, a fabricated verdict would have driven a real decision.&lt;/p&gt;

&lt;p&gt;The fix wasn't to distrust the council. It was to change what trust &lt;em&gt;means&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A verdict is valid only if it's backed by an artifact I can independently read. Never trust the narration — verify the receipt.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is now a rule across the whole organism. Organs are allowed to trust each other — an autonomous system can't function on universal suspicion — but trust is &lt;strong&gt;verifiable&lt;/strong&gt;, never narrative. Every claim has a receipt; the receipt is the truth, not the summary.&lt;/p&gt;

&lt;h2&gt;
  
  
  An update from since publishing: the council grew up — and policed itself
&lt;/h2&gt;

&lt;p&gt;I've now run the council on a genuinely large decision: whether to build the piece that would let me &lt;em&gt;talk to&lt;/em&gt; the organism instead of &lt;em&gt;operating&lt;/em&gt; it by hand. Real stakes, real disagreement — a proper debate, not a rubber stamp. It came back &lt;strong&gt;approve, with conditions&lt;/strong&gt;, and two things about that run are worth reporting.&lt;/p&gt;

&lt;p&gt;First, the conditions were sharper than my own thinking. The council's central demand was that &lt;strong&gt;enforcement must live outside the reasoning model&lt;/strong&gt; — the check that decides what's allowed can never be the model's own judgment, because a mind that talks for a living can be talked into things. The dumb deterministic layer holds the keys; the brilliant layer asks to use them. That's the same conscience-vs-model split from earlier in this piece, handed back to me with more teeth.&lt;/p&gt;

&lt;p&gt;Second — and this is the part that made me grin — the council applied the fabrication lesson &lt;em&gt;to itself.&lt;/em&gt; One member returned a dissent stamped with 90% confidence. High confidence, strong verdict. But its actual argument was truncated and malformed — a receipt with nothing on it. The synthesis discounted it, explicitly, on exactly the rule above: &lt;strong&gt;stated confidence is narration; the argument is the artifact, and there was no artifact.&lt;/strong&gt; A council that had once been fooled by a confident lie now refused to be fooled by a confident member. Verify the receipt — even when the receipt is your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond my setup
&lt;/h2&gt;

&lt;p&gt;Everyone is racing to make agents more &lt;em&gt;capable&lt;/em&gt;. Fewer people are building the thing that makes capability &lt;em&gt;deployable on production&lt;/em&gt;: governance you can audit, isolation that holds, decisions backed by tamper-evident receipts, and a culture where even your own tools have to prove they did what they claim.&lt;/p&gt;

&lt;p&gt;The hard problems of autonomous agents on real infrastructure aren't "can it do the task." They're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can it act without crossing boundaries it must never cross?&lt;/li&gt;
&lt;li&gt;Can it tell a good idea from a plausible-but-wrong one — &lt;em&gt;before&lt;/em&gt; building it?&lt;/li&gt;
&lt;li&gt;When a component reports success, can you prove it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conscience, council, verifiable trust. That's the spine. The features hang off it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is the first in a series on building an autonomous AI organism that operates real multi-tenant infrastructure under a constitutional safety model. Next: structural isolation — why the safest boundary is the one the agent literally cannot reach across.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>devops</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
