<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Agents on bismigel</title><link>https://bismigel.dev/tags/agents/</link><description>Recent content in Agents on bismigel</description><generator>Hugo</generator><language>en-us</language><copyright>bismigel</copyright><lastBuildDate>Tue, 20 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://bismigel.dev/tags/agents/index.xml" rel="self" type="application/rss+xml"/><item><title>An agent for the lab, on a leash</title><link>https://bismigel.dev/posts/2026-10-20-an-agent-for-the-lab/</link><pubDate>Tue, 20 Oct 2026 00:00:00 +0000</pubDate><guid>https://bismigel.dev/posts/2026-10-20-an-agent-for-the-lab/</guid><description/><content:encoded><![CDATA[<p>The fun idea, once the lab was reproducible, was obvious: stop being the only thing that can operate it. Put an agent inside the cluster, give it the tools I would use, and let it do the small work. This is what that turned into, and what it taught me about where an autonomous thing belongs.</p>
<h1 id="what-it-is">What it is</h1>
<p>It is a single workload, deployed the same way as everything else: one ArgoCD application, one container, one persistent volume. It is reachable two ways, both in front of the same identity gate. There is a web dashboard behind Cloudflare Access, and there is a Telegram bot, and the Telegram bot only answers accounts that have been explicitly added to an allowlist. Nobody else gets a reply.</p>
<p>What makes it worth having is not the chat. It is that the box it runs on is not a sandbox. It has a shell, and in that shell are the same tools I would reach for: `kubectl` with real permissions, `gh` and `git`, `helm`, `jq`. It reads the same docs I wrote for myself. So when I ask it to check something, it is not summarising a log I pasted; it is going and looking.</p>
<h1 id="tools-not-just-a-prompt">Tools, not just a prompt</h1>
<p>The part I underrated is the tools. A model with a shell can do anything I can, which is a security problem and a capability at once. The cleaner way to give it structure is MCP servers, which expose a typed set of operations instead of a raw shell.</p>
<p>Two of them turned out to matter. A Kubernetes server gives it first-class tools for pods, resources, events, logs, and Helm, and because it speaks to the API directly it can be pointed at <strong>both</strong> clusters, so the agent sees the whole lab and not just the box it lives on. A GitHub server gives it the repository operations, including the one that matters here, opening a pull request.</p>
<p>The reason to prefer these over the shell is not capability. It is that a styled tool is something I can reason about, name, and gate. A shell is a bottomless allowlist.</p>
<h1 id="the-leash">The leash</h1>
<p>Full autonomy is the easy setting and the wrong default. I want two things from an agent that has the run of the place: that it cannot make a change I would be embarrassed by, and that I can still tell it to go do something without hovering.</p>
<p>The compromise I landed on is a set of rules the agent is given and a small number of constraints it cannot talk its way out of.</p>
<p>The first rule is that it proposes, it does not commit. It works on branches and opens pull requests, and the default branch is protected so that is not a suggestion. The manual review is the point.</p>
<p>The second is about the edge. Cloudflare is the one thing that can expose the house to the internet, so it is the one thing the agent is not trusted with. It does not get the token. Instead there is a little proxy beside it that holds the token and forwards <strong>reads</strong>, and answers every write with a flat no. The agent can look at the DNS, the tunnel, the zones. It cannot change them, and it cannot leak the token because it never has it.</p>
<p>The third is the boring one that is actually the whole thing: secrets live in a store, they are injected as environment variables, and they never land in a file, a prompt, or a log. The agent gets the <strong>name</strong> of a credential and nothing more. Everything else follows from that.</p>
<h1 id="the-model-is-not-the-interesting-part-but-it-is-a-dividing-line">The model is not the interesting part, but it is a dividing line</h1>
<p>It runs on a hosted model, and for a while it was falling back to a small local one when the hosted call failed. That fallback was a mistake, and not a subtle one: the small model could not reliably use tools. It did not just answer worse, it hallucinated that it had no tools at all and refused to act. Capability there is not a linear dial; below some point the tool use just stops working, and the difference between a model that is a little worse and one that cannot do the job is the difference between a feature and an outage.</p>
<p>The local model still has a place as a fallback for conversation, but the agent only works when it is actually allowed to act, and for that it needs a model that can.</p>
<h1 id="what-went-wrong">What went wrong</h1>
<p>The honest one: I had seeded the secret store with placeholder values during setup, using a mechanism that pushes a value on a timer. Then I updated the real values. The leftover job kept pushing, and on its next tick it overwrote the real credentials with the placeholders. The agent then spent an evening being confidently useless, and I spent it assuming the tools were broken. The tools were fine. The credentials had been quietly reverted by my own scaffolding. The lesson is not about agents at all; it is that anything which writes to your source of truth on a schedule will eventually write to it when you are not looking.</p>
<h1 id="what-i-think-now">What I think now</h1>
<p>The value is real but narrow. The agent is good at the same things the model is good at when it writes code: the mechanical, the repetitive, the look-it-up. It is a genuinely useful thing to have a box that can answer &quot;what is actually running, and is it healthy&quot; without me opening a terminal, and that can open the PR to fix the small thing it noticed.</p>
<p>The remaining question is trust, and it is narrower than it sounds. I am not worried about the model being malicious. I am worried about it being confidently wrong at the edge of what it can see, which is the same worry I have about myself. The design answer is the same in both cases: put the parts that cannot be undone behind a human, and let everything else move fast.</p>
]]></content:encoded></item></channel></rss>