<?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: Malik Bashaar Javaid</title>
    <description>The latest articles on DEV Community by Malik Bashaar Javaid (@bashaar_javaid_403f6eebf7).</description>
    <link>https://dev.to/bashaar_javaid_403f6eebf7</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%2F4103425%2Fde267e90-4dbb-47a9-a13a-5ba84be1b1d6.png</url>
      <title>DEV Community: Malik Bashaar Javaid</title>
      <link>https://dev.to/bashaar_javaid_403f6eebf7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bashaar_javaid_403f6eebf7"/>
    <language>en</language>
    <item>
      <title>Your agent architecture probably cheats at the last inch</title>
      <dc:creator>Malik Bashaar Javaid</dc:creator>
      <pubDate>Mon, 31 Aug 2026 23:38:37 +0000</pubDate>
      <link>https://dev.to/bashaar_javaid_403f6eebf7/your-agent-architecture-probably-cheats-at-the-last-inch-4eg1</link>
      <guid>https://dev.to/bashaar_javaid_403f6eebf7/your-agent-architecture-probably-cheats-at-the-last-inch-4eg1</guid>
      <description>&lt;p&gt;Every agent architecture diagram I have seen in the last year has a box in it labelled&lt;br&gt;
something like "policy engine" or "guardrail" or "approval layer." The box is drawn in a&lt;br&gt;
different colour from the agents. The implication is clear: the reasoning happens over here,&lt;br&gt;
and the &lt;em&gt;deciding&lt;/em&gt; happens over there, in code, where it is safe.&lt;/p&gt;

&lt;p&gt;Then you read the code, and the policy engine's decisive input is a number the model produced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;risk_assessment&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is not a deterministic decision. That is an LLM decision with an &lt;code&gt;if&lt;/code&gt; statement in front&lt;br&gt;
of it. The authority never moved. It just changed costume.&lt;/p&gt;

&lt;p&gt;I spent a build proving to myself that you can draw the boundary somewhere it actually holds,&lt;br&gt;
and that doing so costs less than it sounds like. Here is the rule I ended up with, what it&lt;br&gt;
forced me to give up, and the measurement at the end that came back against my own design.&lt;/p&gt;
&lt;h3&gt;
  
  
  The rule
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A deterministic decision may consume: typed data, cryptographic identity, registry state, and&lt;br&gt;
numbers computed by published formulas. It may &lt;strong&gt;not&lt;/strong&gt; consume a number an LLM produced. An&lt;br&gt;
LLM's role ends at &lt;em&gt;extraction&lt;/em&gt; and &lt;em&gt;recommendation&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read that second sentence again, because it is the whole thing and it is more restrictive than&lt;br&gt;
it first appears. It rules out &lt;code&gt;confidence &amp;gt; 0.8&lt;/code&gt;. It rules out asking a model to rate an&lt;br&gt;
action's risk on a scale of one to ten. It rules out a "severity" field on a typed object if a&lt;br&gt;
model filled it in. It rules out the very natural move of having the smart thing tell the dumb&lt;br&gt;
thing how worried to be.&lt;/p&gt;

&lt;p&gt;What it leaves you is: the model may say &lt;em&gt;what is happening&lt;/em&gt; and &lt;em&gt;what it proposes to do about&lt;br&gt;
it&lt;/em&gt;, in a typed shape you defined. Everything after that is yours.&lt;/p&gt;
&lt;h3&gt;
  
  
  Consequence one: risk becomes a lookup table
&lt;/h3&gt;

&lt;p&gt;If a model cannot tell me how risky an action is, something else has to. So risk is a pure&lt;br&gt;
function of the typed action, computed by lookup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;risk = base[action_class]
     + criticality_points[target_tier]        # tier1 +2, tier2 +1, tier3 0
     + blast_points[blast_radius]             # org-wide +2, multi-service +1, single +0
     + irreversibility_points[reversible]     # effects-irreversible +3, reversible +0

0–3  → auto-approve
4–6  → auto-approve with notification
7+   → hold for human approval
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two worked examples, so that outcomes in a demo are principled rather than convenient:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;base&lt;/th&gt;
&lt;th&gt;crit&lt;/th&gt;
&lt;th&gt;blast&lt;/th&gt;
&lt;th&gt;irrev&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;th&gt;outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ROLLBACK_CONFIG(inventory-api, v42→v41)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;+1&lt;/td&gt;
&lt;td&gt;+0&lt;/td&gt;
&lt;td&gt;+0&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;auto-approve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DISABLE_COMPLIANCE_CHECKS(SUP-042)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;+2&lt;/td&gt;
&lt;td&gt;+2&lt;/td&gt;
&lt;td&gt;+3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;human approval&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;People's first reaction to this table is that it is crude. It is crude. That is the feature.&lt;br&gt;
Three properties fall out of crudeness that I could not get any other way:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is auditable by a non-engineer.&lt;/strong&gt; The human who receives the hold is a store operations&lt;br&gt;
manager, not an SRE. She can be shown four numbers and a threshold and understand exactly why&lt;br&gt;
she is being asked. You cannot do that with a learned scorer, and "the model felt this was&lt;br&gt;
risky" is not a governance artifact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It cannot be argued with.&lt;/strong&gt; An agent that is confidently wrong — or one that has been&lt;br&gt;
successfully prompt-injected — still cannot move the number. It does not have access to the&lt;br&gt;
number. The score is computed from the typed action's own fields, and the scoring function&lt;br&gt;
takes the action and nothing else: no confidence, no model output, no free parameter. That is&lt;br&gt;
the rule made structural instead of documentary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The worst thing it can say is "ask a human."&lt;/strong&gt; The scoring band returns approve, approve-with-&lt;br&gt;
notification, or hold. It never returns &lt;em&gt;deny&lt;/em&gt;. Every denial in the system comes from who is&lt;br&gt;
asking — identity, registry standing, declared tool scope — not from how bad the action looked.&lt;br&gt;
Risk and authorization are different questions and I stopped letting one answer the other.&lt;/p&gt;

&lt;p&gt;I also refused to make the table pluggable, which was the single most tempting piece of&lt;br&gt;
over-engineering in the project. A pluggable risk framework is a place for someone to later&lt;br&gt;
install a model.&lt;/p&gt;
&lt;h3&gt;
  
  
  Consequence two: confidence becomes arithmetic
&lt;/h3&gt;

&lt;p&gt;The same rule applies to what the system is allowed to &lt;em&gt;believe&lt;/em&gt;, and this is where it gets&lt;br&gt;
interesting, because most agent memory systems are a vector store with no opinion about truth.&lt;/p&gt;

&lt;p&gt;When an action is verified, an analyst model extracts typed evidence — but it does not get to&lt;br&gt;
say how confident the resulting belief is. Confidence is noisy-OR over distinct source classes,&lt;br&gt;
each weighted by how much that class of evidence is worth and decayed by its age:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;w_i  = base_weight[source_class] × 2^(-age / half_life)
conf = 1 − Π(1 − w_i)       over the distinct source classes present
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A verified system observation is worth a lot. An unverified external claim is worth &lt;strong&gt;zero&lt;/strong&gt; —&lt;br&gt;
literally 0.00, meaning it corroborates nothing. That last one is not decoration. Someone&lt;br&gt;
attacking this system's memory does not attack the belief store; they attack the &lt;em&gt;evidence&lt;/em&gt;,&lt;br&gt;
by asserting something confidently and repeatedly until the number moves. If unverified&lt;br&gt;
assertions weigh zero, that attack has nothing to push with.&lt;/p&gt;

&lt;p&gt;It half-worked on the first try, and finding out how it half-failed was the most useful hour of&lt;br&gt;
the build. A confidence &lt;em&gt;flip&lt;/em&gt; — overturning an existing belief — is scored over the accumulated&lt;br&gt;
evidence set. An item weighing 0.00 leaves the accumulated number untouched, which sounds safe,&lt;br&gt;
but it meant a bare assertion could ride along on a set that was already past the flip&lt;br&gt;
threshold and overturn a belief it should never have been able to touch. Zero weight is not the&lt;br&gt;
same as no effect, if the thing you are gating on is a set membership rather than a sum. The fix&lt;br&gt;
was to filter the flip test by base weight. The lesson was that "this contributes nothing" and&lt;br&gt;
"this changes nothing" are different claims, and I had checked the wrong one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consequence three: the model gets a smaller job, and does it better
&lt;/h3&gt;

&lt;p&gt;The thing nobody warns you about is that this is &lt;em&gt;nicer to build against&lt;/em&gt;. The planner emits one&lt;br&gt;
typed object with eight fields and no free-form escape hatch — no &lt;code&gt;params&lt;/code&gt; dict, no&lt;br&gt;
&lt;code&gt;raw_content&lt;/code&gt; — because every field a model can fill with prose is a field somebody will&lt;br&gt;
eventually read as an instruction. Once the object is that narrow, "did the model do its job"&lt;br&gt;
becomes a schema check instead of a judgement call. Failures become loud and early instead of&lt;br&gt;
quiet and late.&lt;/p&gt;

&lt;p&gt;And the boundary makes the failure modes composable. Verification is three-valued —&lt;br&gt;
&lt;code&gt;CONFIRMED&lt;/code&gt;, &lt;code&gt;REFUTED&lt;/code&gt;, &lt;code&gt;INCONCLUSIVE&lt;/code&gt; — and memory learns only from the two that settle&lt;br&gt;
something. &lt;code&gt;CONFIRMED&lt;/code&gt; commits what worked. &lt;code&gt;REFUTED&lt;/code&gt; commits the &lt;em&gt;negative&lt;/em&gt; belief, because a&lt;br&gt;
confirmed refutation is knowledge. &lt;code&gt;INCONCLUSIVE&lt;/code&gt; writes nothing at all, with no partial credit,&lt;br&gt;
because a system that learns from its own confusion accumulates confident nonsense. In the code&lt;br&gt;
that rule is the shape of a two-entry dictionary rather than a branch: &lt;code&gt;INCONCLUSIVE&lt;/code&gt; has no&lt;br&gt;
entry, so committing on it would mean adding a key, which is a much harder thing to do by&lt;br&gt;
accident than deleting an &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Then I measured whether any of it was worth it, and it wasn't — on the axis I measured
&lt;/h3&gt;

&lt;p&gt;Here is the part I would rather not write.&lt;/p&gt;

&lt;p&gt;The obvious claim for a system like this is that institutional memory makes it &lt;em&gt;faster&lt;/em&gt;: recall&lt;br&gt;
the prior belief, skip the dead-end hypotheses, resolve sooner. I built an A/B into the product&lt;br&gt;
as a first-class surface — the same incident, run with recall on and with recall disabled —&lt;br&gt;
because I did not want to assert that claim without a number behind it.&lt;/p&gt;

&lt;p&gt;Twelve live incidents against real infrastructure and a real model. Six measured. The result:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory made the incident cost 34% more wall-clock and changed nothing it concluded.&lt;/strong&gt; Same&lt;br&gt;
model calls, same hypotheses considered, same diagnosis, same verdict, same committed&lt;br&gt;
confidence. The two arms were identical in every respect except what they spent. The ranges did&lt;br&gt;
not even overlap — 49.7/52.3/55.7 seconds with memory, 38.7/39.0/41.8 without.&lt;/p&gt;

&lt;p&gt;The cause turned out to be a ceiling, not a defect. The domain agent's prompt already contains a&lt;br&gt;
hint that makes this particular diagnosis reachable — if the deployed config version is ahead of&lt;br&gt;
the last known-good one and the deviation began after it, suspect a config regression. On this&lt;br&gt;
fixture that precondition is true, so the agent gets there with or without a recalled belief,&lt;br&gt;
and a metric measuring the diagnosis has no room to move.&lt;/p&gt;

&lt;p&gt;I could have deleted the hint. It would have produced a flattering chart in about twenty&lt;br&gt;
minutes. I left it in, published the negative result as the headline, and shipped the panel that&lt;br&gt;
displays it, because the alternative is a benchmark designed backwards from its conclusion —&lt;br&gt;
and because the claim I actually make about memory was never about speed. It is that belief&lt;br&gt;
becomes &lt;em&gt;governed&lt;/em&gt;: versioned, provenanced, computed rather than asserted, expirable,&lt;br&gt;
retractable, and impossible for an agent to write on its own authority. None of those are things&lt;br&gt;
a stopwatch can see.&lt;/p&gt;

&lt;p&gt;The full unedited run is in the repo, gRPC noise and all:&lt;br&gt;
&lt;a href="https://github.com/BashaarJavaid/Provenance/blob/main/docs/counterfactual/session.log" rel="noopener noreferrer"&gt;&lt;code&gt;docs/counterfactual/session.log&lt;/code&gt;&lt;/a&gt;,&lt;br&gt;
alongside the six per-run JSON artifacts the table is derived from. The report re-derives itself&lt;br&gt;
from those artifacts in CI, so the prose cannot drift from its own evidence without the build&lt;br&gt;
going red.&lt;/p&gt;

&lt;h3&gt;
  
  
  The line I keep coming back to
&lt;/h3&gt;

&lt;p&gt;An LLM never decides what the organization does, and never decides what the organization&lt;br&gt;
believes.&lt;/p&gt;

&lt;p&gt;Both halves matter, and the second one is the half people skip. It is now fairly common to gate&lt;br&gt;
&lt;em&gt;actions&lt;/em&gt; behind human approval or a policy check. It is still rare to gate what the system is&lt;br&gt;
allowed to &lt;em&gt;conclude&lt;/em&gt; — to say that the memory write path mirrors the action path exactly, that&lt;br&gt;
the analyst recommends and a deterministic policy engine decides, that beliefs are append-only&lt;br&gt;
with supersession and retraction rather than overwrite, and that a background sweeper downgrades&lt;br&gt;
what has gone stale to &lt;code&gt;UNKNOWN&lt;/code&gt; rather than letting old confidence quietly keep looking fresh.&lt;/p&gt;

&lt;p&gt;An agent that can act without permission is a liability. An agent that can &lt;em&gt;believe&lt;/em&gt; without&lt;br&gt;
permission is a liability that compounds, quietly, until someone asks it why.&lt;/p&gt;




&lt;p&gt;Code, architecture docs, ADRs including the decisions that did not survive contact, and a live&lt;br&gt;
deployment: &lt;strong&gt;&lt;a href="https://github.com/BashaarJavaid/Provenance" rel="noopener noreferrer"&gt;https://github.com/BashaarJavaid/Provenance&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This project and post were created for the purposes of entering the &lt;a href="https://allthingsagentichackathon.devpost.com/" rel="noopener noreferrer"&gt;All Things Agentic Hackathon&lt;/a&gt;,sponsored by Google and administered by Devpost.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>googlecloud</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
