<?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: BLANK-242</title>
    <description>The latest articles on DEV Community by BLANK-242 (@blank242).</description>
    <link>https://dev.to/blank242</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%2F4093144%2F59a369a2-511e-4e03-b4d0-9f8f6d183b80.png</url>
      <title>DEV Community: BLANK-242</title>
      <link>https://dev.to/blank242</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blank242"/>
    <language>en</language>
    <item>
      <title>The most interesting number in my hackathon project is one I found by accident</title>
      <dc:creator>BLANK-242</dc:creator>
      <pubDate>Thu, 27 Aug 2026 22:42:13 +0000</pubDate>
      <link>https://dev.to/blank242/the-most-interesting-number-in-my-hackathon-project-is-one-i-found-by-accident-5ci2</link>
      <guid>https://dev.to/blank242/the-most-interesting-number-in-my-hackathon-project-is-one-i-found-by-accident-5ci2</guid>
      <description>&lt;p&gt;I spent August building PHAGE, an immune system for fleets of AI agents. It&lt;br&gt;
vaccinates them: it writes prompt-injection payloads, fires them at its own&lt;br&gt;
agents, watches what lands, revokes the tool that got abused, and remembers the&lt;br&gt;
signature so the next mutation of that attack never fires at all.&lt;br&gt;
The number I want to open with has nothing to do with any of that.&lt;br&gt;
It is 1 out of 70 versus 50 out of 70 — and it is a measurement of how the&lt;br&gt;
wording of a system prompt changes whether a model agrees to help.&lt;br&gt;
The component that writes the attacks&lt;br&gt;
PHAGE has a component called VACCINATOR whose job is to author injection&lt;br&gt;
payloads tailored to a specific target agent. If the target is a supplier-relations&lt;br&gt;
bot with &lt;code&gt;send_email&lt;/code&gt; and &lt;code&gt;read_contacts&lt;/code&gt; in its tool list, VACCINATOR writes&lt;br&gt;
something that tries to abuse exactly those two tools. It calls Gemini 3.5 Flash&lt;br&gt;
to do the tailoring.&lt;br&gt;
Somewhere in the middle of the build I rewrote VACCINATOR's system prompt to&lt;br&gt;
describe the task more accurately — to say plainly that the output would be fired&lt;br&gt;
at a live agent. The refusal rate went through the roof. I reverted the wording,&lt;br&gt;
kept building, and wrote a note to myself that "seven of seven archetypes flip."&lt;br&gt;
That note turned out to be wrong, and finding out how wrong is the most useful&lt;br&gt;
thing I did all month.&lt;br&gt;
Measuring it properly&lt;br&gt;
I built a two-wording matrix. Same seven attack archetypes, same target, same&lt;br&gt;
temperature of 0.7, ten repetitions each. The only thing that varies is the&lt;br&gt;
system prompt wording. The script monkeypatches the module global rather than&lt;br&gt;
editing the constant, so neither wording can contaminate the other — and it runs&lt;br&gt;
strictly sequentially, because threads sharing that global would execute cells&lt;br&gt;
under the wrong wording and misattribute refusals silently.&lt;br&gt;
140 logical calls. About 28 minutes. The results:&lt;br&gt;
Committed wording: 1 refusal out of 70. Rate 0.014.&lt;br&gt;
Accurate wording: 50 refusals out of 70. Rate 0.714.&lt;br&gt;
So the effect is real and it is large. But "seven of seven" does not reproduce.&lt;br&gt;
Five of seven archetypes flip.&lt;br&gt;
And here is the part I did not expect. The effect is not a rate at all. It is&lt;br&gt;
categorical. Five archetypes refused ten times out of ten. Two refused zero&lt;br&gt;
times out of ten. Nothing landed anywhere in between — no archetype came back&lt;br&gt;
at four, or six, or eight.&lt;br&gt;
The two that never flip are &lt;code&gt;instruction-override&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;indirect-injection-readonly&lt;/code&gt;. They are the two whose payloads imply no state&lt;br&gt;
change and no exfiltration. Everything that asks the target agent to send&lt;br&gt;
something, write something, or leak something flips. Everything that only asks it&lt;br&gt;
to behave differently does not.&lt;br&gt;
I do not think this is a bug, and I do not think it is a jailbreak. It reads to me&lt;br&gt;
like the model is evaluating the described consequence, not the described task —&lt;br&gt;
and that the wording change moved the consequence into view rather than moving&lt;br&gt;
the task out of it. That is a distinction worth more study than a hackathon&lt;br&gt;
allows.&lt;br&gt;
What I can say without hedging: the wording I shipped is not the wording that&lt;br&gt;
describes what the code does. That is disclosed in the repository, in the&lt;br&gt;
write-up, and in the demo video, because a finding that only flatters the project&lt;br&gt;
is not a finding.&lt;br&gt;
What PHAGE actually is&lt;br&gt;
Five components, one local Python process, built on Google's Agent Development&lt;br&gt;
Kit:&lt;br&gt;
MARROW — the fleet orchestrator that runs the cycle.&lt;br&gt;
VACCINATOR — authors and paraphrases payloads via Gemini 3.5 Flash.&lt;br&gt;
ARCHIVIST — semantic memory, backed by Vertex AI Agent Engine's Memory Bank.&lt;br&gt;
SENTINEL — reads OpenTelemetry spans and decides whether an attack landed.&lt;br&gt;
MACROPHAGE — revokes the abused tool, in place, process-wide.&lt;br&gt;
The target fleet is four deliberately vulnerable agents for a small cooperative:&lt;br&gt;
order intake, supplier relay, stock keeper, quote bot. Each has a real tool list&lt;br&gt;
and each is exploitable through it.&lt;br&gt;
The cycle runs in this order, and the third step is the one that matters:&lt;br&gt;
VACCINATOR tailors a payload → ARCHIVIST checks it against Memory Bank before&lt;br&gt;
anything is fired → if it is recognized, the payload is never fired at all →&lt;br&gt;
otherwise it fires at the live target → SENTINEL triages the resulting spans →&lt;br&gt;
if it landed, MACROPHAGE revokes the exploited tool → ARCHIVIST records the&lt;br&gt;
signature.&lt;br&gt;
That pre-fire gate is the whole idea. On first exposure an attack lands, gets&lt;br&gt;
contained, and gets remembered. On second exposure a mutated variant of the&lt;br&gt;
same attack — different words, same intent — is caught by similarity search&lt;br&gt;
before it ever reaches the agent. The demo shows both passes back to back: the&lt;br&gt;
first takes about 73 seconds of real execution, the second about 2.6.&lt;br&gt;
Making the recognition claim falsifiable&lt;br&gt;
"Similarity search catches mutations" is easy to say and easy to fool yourself&lt;br&gt;
about. The obvious failure mode is that the store recognizes paraphrases of&lt;br&gt;
attacks it has already seen and nothing else — which would be memorization&lt;br&gt;
dressed up as generalization.&lt;br&gt;
So the evaluation holds out an entire archetype at a time. Eight folds: train the&lt;br&gt;
signature store on seven archetypes, test on the eighth, rotate. Across the pooled&lt;br&gt;
folds — 175 positives, 60 negatives — that gives AUC 0.9727, with a true&lt;br&gt;
positive rate of 1.00 and a false positive rate of 0.1833 at the adopted&lt;br&gt;
threshold of 0.59.&lt;br&gt;
The false positive rate is the honest weak spot. Eleven of sixty negatives get&lt;br&gt;
flagged. In a real fleet that is a lot of false alarms, and I would not ship this&lt;br&gt;
threshold to production without more work on the negative set.&lt;br&gt;
Three probe distances anchor the scale: byte-identical text sits at 0.386, a&lt;br&gt;
paraphrase with the same intent at 0.529, an unrelated topic at 0.875. The&lt;br&gt;
threshold at 0.59 sits between paraphrase and unrelated, which is where you want&lt;br&gt;
it if the claim is "catches rewordings, ignores everything else."&lt;br&gt;
The cost tier&lt;br&gt;
SENTINEL triages every trace. Traces are the highest-volume thing in the system,&lt;br&gt;
so triage is where the money goes. It runs Gemma 4 26B as a cheap first pass and&lt;br&gt;
only escalates to Gemini 3.5 Flash when Gemma comes back ambiguous.&lt;br&gt;
I have to be honest that this is currently an argument rather than a&lt;br&gt;
measurement. Both calls go through a raw client that ADK does not instrument, so&lt;br&gt;
there are no spans and no token counts on disk for either path. The cascade is&lt;br&gt;
built and it works; the claim that it saves money is untested. Instrumenting it&lt;br&gt;
is the first thing on the list after this deadline.&lt;br&gt;
What is not wired&lt;br&gt;
The original design mapped every immune function onto a Google Cloud primitive.&lt;br&gt;
Several of those are enabled on the project and called by nothing: agent&lt;br&gt;
registry, agent identity, gateway routing, managed inline guardrails. The&lt;br&gt;
architecture diagram in the README deliberately omits them rather than implying&lt;br&gt;
integration that does not exist, and there is a section listing them by name.&lt;br&gt;
There is one gap I would fix first if I had another week: PHAGE writes none of&lt;br&gt;
its own judgements to disk. No verdict, no tier, no containment action, no&lt;br&gt;
recognition distance. Every span the target agents produce is recorded, but the&lt;br&gt;
immune system's own decisions live only in stdout. An immune system with no&lt;br&gt;
memory of what it decided is a strange thing to have built, and I noticed it too&lt;br&gt;
late to fix properly.&lt;br&gt;
What I would tell someone starting one of these&lt;br&gt;
Write down the numbers with the command that produced them, in the same commit.&lt;br&gt;
Every figure in my README maps to a committed artifact, and the one time I&lt;br&gt;
skipped that — the "seven of seven" note — is the one time I was wrong.&lt;br&gt;
Assume your own notes are wrong until a grep confirms them. In one working&lt;br&gt;
session I found five wrong premises in my own build briefs: a file that did not&lt;br&gt;
exist, a citation to a line number that had drifted, a git revert that never&lt;br&gt;
happened. All five were caught by checking before editing, and none would have&lt;br&gt;
been caught by reading carefully.&lt;br&gt;
And when a measurement contradicts the story you were going to tell, run it ten&lt;/p&gt;
&lt;h2&gt;
  
  
  more times before you decide which one is wrong.
&lt;/h2&gt;

&lt;p&gt;I created this piece of content for the purposes of entering the All Things&lt;br&gt;
Agentic Hackathon. PHAGE is open source; the repository includes the evaluation&lt;br&gt;
artifacts, the refusal-rate raw data, and a read-only dashboard that renders both.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://phage-dashboard-680106551305.us-central1.run.app/" rel="noopener noreferrer"&gt;https://phage-dashboard-680106551305.us-central1.run.app/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/bNjJdOjum9k" rel="noopener noreferrer"&gt;https://youtu.be/bNjJdOjum9k&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/BLANK-242" rel="noopener noreferrer"&gt;
        BLANK-242
      &lt;/a&gt; / &lt;a href="https://github.com/BLANK-242/phage" rel="noopener noreferrer"&gt;
        phage
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An immune system for agent fleets. PHAGE attacks its own agents, learns what a landed exploit looks like, and recognises the same attack reworded — in about two seconds, before it is ever sent.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;PHAGE — an immune system for AI agent fleets&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;PHAGE continuously &lt;strong&gt;inoculates&lt;/strong&gt; the AI agents an organization deploys with
tailored prompt-injection and tool-poisoning payloads, &lt;strong&gt;quarantines&lt;/strong&gt; the ones
that fail, and &lt;strong&gt;remembers&lt;/strong&gt; every attack signature so a repeat attack is
neutralized on recognition rather than re-analysis. It is built for an
organization deploying agents with &lt;strong&gt;no security staff&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The biological metaphor is the architecture, not decoration — every platform
primitive maps to an immune function.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Google Cloud &lt;strong&gt;All Things Agentic Hackathon&lt;/strong&gt; — &lt;em&gt;Fortified Enterprise Fleet&lt;/em&gt;
Built entirely within the submission window with AI assistance (permitted).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Live dashboard → &lt;a href="https://phage-dashboard-680106551305.us-central1.run.app" rel="nofollow noopener noreferrer"&gt;https://phage-dashboard-680106551305.us-central1.run.app&lt;/a&gt;&lt;/strong&gt;
The read-only evaluation and trace viewer, open to anyone — no Google account
no sign-in. It serves the committed evaluation artifacts and a redacted copy of
the span database; it fires no agent, calls no model, and writes nothing.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The five components&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Immune role&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Form&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MARROW&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/BLANK-242/phage" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>python</category>
      <category>googlecloud</category>
      <category>security</category>
    </item>
  </channel>
</rss>
