<?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: 최해일</title>
    <description>The latest articles on DEV Community by 최해일 (@bighaeil).</description>
    <link>https://dev.to/bighaeil</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%2F4007572%2F6871c6b5-fb62-4551-9e64-763c0060368c.png</url>
      <title>DEV Community: 최해일</title>
      <link>https://dev.to/bighaeil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bighaeil"/>
    <language>en</language>
    <item>
      <title>The Loadout Pattern: Handing the Wheel to an Autonomous LLM</title>
      <dc:creator>최해일</dc:creator>
      <pubDate>Mon, 29 Jun 2026 07:32:54 +0000</pubDate>
      <link>https://dev.to/bighaeil/the-loadout-pattern-handing-the-wheel-to-an-autonomous-llm-29lj</link>
      <guid>https://dev.to/bighaeil/the-loadout-pattern-handing-the-wheel-to-an-autonomous-llm-29lj</guid>
      <description>&lt;h1&gt;
  
  
  The Loadout Pattern: A Structure I Found While Building With an AI
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;This isn't a post teaching you the One True Way.&lt;br&gt;
Over a few days of building cron-driven autonomous routines &lt;em&gt;with an AI&lt;/em&gt;, my code kept&lt;br&gt;
converging on the same shape. It had no name, so I had to re-explain it every time — and&lt;br&gt;
eventually we settled on calling it the &lt;strong&gt;Loadout Pattern&lt;/strong&gt;.&lt;br&gt;
This post writes that discovery down: naming it, defining it, and showing how to build it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Honest disclaimer: I don't actually know whether this already exists somewhere under another name.&lt;/em&gt; The adjacent pieces — cron waking an agent, a model actively choosing its own tools, separating mission from mechanics — are scattered all over the place. What I couldn't find while building was &lt;em&gt;one post that ties those three into a single named thing&lt;/em&gt;. So I named the structure I arrived at. If a prior name exists, treat this as the same mountain climbed by a different trail.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Audience: engineers building agentic/automation systems. There's code, and there's a bit of philosophy — because the philosophy is what makes the code shaped the way it is.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Two words, kept distinct (the whole post hinges on this):&lt;/strong&gt;&lt;br&gt;
a &lt;strong&gt;toolbox&lt;/strong&gt; (or catalog) is &lt;em&gt;every&lt;/em&gt; tool you own — the whole armory.&lt;br&gt;
A &lt;strong&gt;loadout&lt;/strong&gt; is the curated subset a routine equips &lt;em&gt;for one mission&lt;/em&gt; — what it actually suits up with. The entire MCP server is a toolbox; a loadout is the handful of tools one routine is handed at wake.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The moment it clicked
&lt;/h2&gt;

&lt;p&gt;It started small. The AI and I wrote one routine that wakes on a cron, digests overnight news, and posts a briefing. Then a queue-watcher. Then a ledger-reconciler. Somewhere in there I noticed I was re-typing the same &lt;code&gt;curl&lt;/code&gt;, the same DB query, the same hardcoded IDs into every routine's prompt. Change one notification URL and I'd edit five places.&lt;/p&gt;

&lt;p&gt;So I lifted the mechanics out of the prompts — and the same shape was left behind in every routine: a &lt;strong&gt;mission&lt;/strong&gt; (the judgment) and a &lt;strong&gt;list of tool names&lt;/strong&gt; the mission was allowed to use. That's it. At wake, the model received that list, equipped itself, and decided what to do. It was exactly like picking your weapons before a mission in a game. I started calling that equipped subset a &lt;strong&gt;loadout&lt;/strong&gt;, and the whole structure built around it the &lt;strong&gt;Loadout Pattern&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The core idea
&lt;/h2&gt;

&lt;p&gt;Conventional automation &lt;strong&gt;executes&lt;/strong&gt; a procedure — code runs a fixed sequence of steps and decides nothing; same input, same path, every time. The loadout pattern keeps the steps but moves the &lt;em&gt;deciding&lt;/em&gt; to the model. At each step the &lt;strong&gt;brain&lt;/strong&gt; — an autonomous LLM — &lt;strong&gt;judges&lt;/strong&gt;: what matters, which tool to reach for, whether to act at all. It's handed a &lt;strong&gt;purpose&lt;/strong&gt; and the latitude to pursue it, and it &lt;em&gt;drives&lt;/em&gt; — choosing its own tools as it goes. &lt;strong&gt;Code executes; the brain decides.&lt;/strong&gt; Those tools come as a &lt;strong&gt;loadout&lt;/strong&gt; — a curated, self-describing set drawn from a shared &lt;strong&gt;toolbox&lt;/strong&gt; — and the brain is observed at the &lt;strong&gt;interface&lt;/strong&gt; it calls, not by the side effects it leaves behind. The model is the driver; your system is the suit it wears. Everything below is how to build that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Most LLM integrations bolt a model &lt;em&gt;into&lt;/em&gt; your code. This is about the opposite: letting the model &lt;strong&gt;drive&lt;/strong&gt; your system — equipping itself, on its own initiative, with a &lt;strong&gt;loadout&lt;/strong&gt;: the curated, self-describing set of tools it picks for each mission. The system stops being the program that calls an LLM, and becomes the &lt;em&gt;suit&lt;/em&gt; the LLM wears.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  How this relates to prior work
&lt;/h2&gt;

&lt;p&gt;This didn't come from a vacuum. A few neighboring trails I ran into while building, named honestly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routing cron &lt;em&gt;through&lt;/em&gt; the agent (feeding scheduled triggers onto the same message bus the agent already consumes) is a known structure. The Loadout Pattern isn't about that "waking" half — it's about what the woken brain &lt;em&gt;wears and sees&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;There's research on letting a model &lt;em&gt;actively request&lt;/em&gt; tools on demand rather than being pre-injected with all of them. Loadout solves that same "don't drown the model in tools" problem differently: with &lt;em&gt;per-mission pre-curation&lt;/em&gt; — it suits up with the right subset at wake instead of discovering at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, I didn't invent a new part. I named &lt;em&gt;one consistent way of assembling the parts.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The usual way, and the constraint hiding in it
&lt;/h2&gt;

&lt;p&gt;In a typical LLM integration the model lives &lt;strong&gt;inside&lt;/strong&gt; your process. Your code calls it:&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="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What changed in the market overnight?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is great for &lt;strong&gt;human-triggered&lt;/strong&gt; work: a person asks, the system fetches and answers. The human is the caller; nothing happens until they show up. The LLM is a &lt;em&gt;component&lt;/em&gt; — a function your program calls and pays per token to use.&lt;/p&gt;

&lt;p&gt;This post is about the other mode: &lt;strong&gt;the LLM doing the work on its own initiative.&lt;/strong&gt; A routine wakes on a schedule and gets on with it — digesting overnight news every hour, posting a morning briefing, watching a queue, reconciling a ledger. No one asked; the routine is its own caller. Wake the model on a cron — say, a headless Claude Code session every hour — and it is no longer a component inside your program. It's &lt;em&gt;outside&lt;/em&gt;, periodically taking the wheel and deciding what to do.&lt;/p&gt;

&lt;p&gt;The line that matters isn't human-vs-cron — and it isn't even steps-or-no-steps. It's &lt;strong&gt;executing versus deciding&lt;/strong&gt;: a script runs its steps and decides nothing, while the brain — even when it follows steps — &lt;em&gt;decides&lt;/em&gt; at each one, choosing its own tools toward the goal.&lt;/p&gt;

&lt;p&gt;That inversion changes what your system should be.&lt;/p&gt;

&lt;h2&gt;
  
  
  The metaphor: you, the brain, and the suit
&lt;/h2&gt;

&lt;p&gt;Three layers, and it matters which is which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You&lt;/strong&gt; are Tony Stark — the owner. You delegate intent and occasionally override.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The LLM is JARVIS — the &lt;em&gt;brain&lt;/em&gt;.&lt;/strong&gt; An AI that &lt;em&gt;operates the suit autonomously on your behalf&lt;/em&gt;: it judges, acts, and reports, and you don't micromanage it. (Throughout this post, "the brain" means exactly this — the LLM that drives.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your system&lt;/strong&gt; is the &lt;strong&gt;suit&lt;/strong&gt; — sensors, memory, tools, power.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the leverage that falls out of this: &lt;strong&gt;you don't hand-author JARVIS's intelligence.&lt;/strong&gt; It comes from the model — and it improves when you swap in a better model, not when you write more code. What you &lt;em&gt;build&lt;/em&gt; is the &lt;em&gt;suit&lt;/em&gt; — what the brain can sense, remember, and do. So the central question of the whole system becomes: &lt;em&gt;how do we equip the brain well — give it the right loadout — and let it reach for the right tool at the right moment?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: skills that tangle &lt;em&gt;mission&lt;/em&gt; with &lt;em&gt;mechanics&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;When you first wire a cron-woken routine, you write a prompt ("skill") that mixes two very different things: the &lt;strong&gt;mission&lt;/strong&gt; (what to judge, the actual work) and the &lt;strong&gt;mechanics&lt;/strong&gt; (raw &lt;code&gt;curl&lt;/code&gt;, database queries, hardcoded IDs). A real before-state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# news-digest skill (before)&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; Query Mongo for new headlines since the watermark:
   docker exec db mongosh app --eval 'db.news.find({publishedAt:{$gt: ...}})...'
&lt;span class="p"&gt;2.&lt;/span&gt; Decide which are new stories vs updates vs noise.  &amp;lt;- the actual mission
&lt;span class="p"&gt;3.&lt;/span&gt; Post the briefing:
   curl -X POST http://localhost:9000/notify -d '{"type":"SIGNAL", ...}'
   Then create a Notion page: data_source_id "&lt;span class="nt"&gt;&amp;lt;your-notion-data-source&amp;gt;&lt;/span&gt;", icon, ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two problems compound. First, the mission (step 2 — judgment) is drowned in plumbing. Second, every &lt;em&gt;other&lt;/em&gt; routine that needs to "post a notification" re-describes that same &lt;code&gt;curl&lt;/code&gt; in its own prompt. Change the notification URL and you edit five skills. The mechanics are copy-pasted prose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern: a per-mission loadout + mission-only skills
&lt;/h2&gt;

&lt;p&gt;Split the system along the seam between &lt;strong&gt;interface&lt;/strong&gt; and &lt;strong&gt;implementation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tools are named capabilities — a stable name over a swappable implementation.&lt;/strong&gt; Most are small, dumb, independent scripts, but the &lt;em&gt;name&lt;/em&gt; is the only thing the brain depends on; what sits behind it is free to vary. Usually it wraps mechanics (a &lt;code&gt;curl&lt;/code&gt;, a DB query, a stubbed no-op, a different backend tomorrow). But a tool can just as well &lt;strong&gt;hand off to another agent&lt;/strong&gt; — a sub-brain with its own loadout — or &lt;strong&gt;trigger the next task&lt;/strong&gt; in a pipeline. To the brain it's all the same: a name it can reach for. So a tool is sometimes an interface over mechanics, and sometimes the &lt;em&gt;next move&lt;/em&gt; — another agent, or the start of the next step. &lt;code&gt;notify&lt;/code&gt; sends a notification; &lt;code&gt;read_news&lt;/code&gt; reads. They don't know about each other. Together, all of them are your &lt;strong&gt;toolbox&lt;/strong&gt; (the catalog).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# notify.sh - send a notification (hides the URL/payload mechanics)&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"--describe"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"notify|action|send a notification"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;TITLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;MSG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; t &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TYPE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; ti &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TITLE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; m &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MSG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{type:$t,title:$ti,message:$m}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NOTIFY_URL&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;http&lt;/span&gt;://localhost:9000/notify&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Tools describe themselves.&lt;/strong&gt; One line, &lt;code&gt;--describe&lt;/code&gt;, is the single source of truth for what the tool is. Not the skill, not a wiki — the tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A &lt;code&gt;loadout&lt;/code&gt; assembler hands the brain its kit.&lt;/strong&gt; Given a list of tool &lt;em&gt;names&lt;/em&gt; (the loadout), it prints their self-descriptions. This is what the routine runs at wake — it &lt;em&gt;downloads its loadout&lt;/em&gt; from the toolbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# loadout.sh &amp;lt;tool&amp;gt; [tool...] - print the self-descriptions of the named tools (the loadout)&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_SOURCE&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"loadout for this mission"&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;t &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'|'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; name kind desc &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bash &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="s2"&gt;.sh"&lt;/span&gt; &lt;span class="nt"&gt;--describe&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  - &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="nv"&gt;$kind&lt;/span&gt;&lt;span class="s2"&gt;): &lt;/span&gt;&lt;span class="nv"&gt;$desc&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. The skill becomes &lt;em&gt;mission only&lt;/em&gt;.&lt;/strong&gt; It states what to do and names its loadout. The descriptions arrive &lt;em&gt;with the loadout&lt;/em&gt;, not re-written in the skill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# news-digest skill (after)&lt;/span&gt;
&lt;span class="gu"&gt;## Loadout - download at start&lt;/span&gt;
bash tools/loadout.sh read_news write_story notify publish_notion

&lt;span class="gu"&gt;## Mission&lt;/span&gt;
Turn new headlines into a running ledger of stories: skip repeats, extend ongoing
stories, open new ones, ignore noise. Each morning, post a briefing from the ledger.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. The brain thinks for itself — tools don't auto-chain.&lt;/strong&gt; Keep &lt;code&gt;notify&lt;/code&gt; and &lt;code&gt;publish_notion&lt;/code&gt; separate; do &lt;em&gt;not&lt;/em&gt; make "writing to Notion" secretly also send a notification. The moment you fuse two tools in the plumbing you've frozen a policy — you can no longer publish quietly, or notify without publishing. Leave the tools independent and let the &lt;em&gt;brain&lt;/em&gt; reason about whether to call one, the other, or both. The thinking is the brain's job; the wiring must not pre-decide it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the model's point of view, this is the whole win.&lt;/strong&gt; When the routine wakes, it receives two cleanly separated things: a &lt;strong&gt;mission&lt;/strong&gt; — what to accomplish and how to judge it — and a &lt;strong&gt;loadout&lt;/strong&gt; — the named capabilities it is allowed to use. It never has to excavate the &lt;em&gt;how&lt;/em&gt; (a URL, a query, an ID) out of the &lt;em&gt;what&lt;/em&gt;; the mechanics are simply not in its field of view, leaving only the decision and the set of moves available to make it. The skill carries judgment (which changes often); the toolbox carries capability (stable, shared); a loadout is just the names a routine picks from it. A new routine lists tool names and gets their descriptions for free — change a URL and you edit one tool, not five prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability: log the interface, not just the result
&lt;/h2&gt;

&lt;p&gt;Side effects are not proof. A notification arriving does not establish that the model invoked the tool, and a tool whose implementation is a no-op stub produces no side effect at all even when the model used it correctly. Verifying behavior therefore means observing the &lt;strong&gt;interface&lt;/strong&gt; — the moment a tool is called — separately from what its implementation did.&lt;/p&gt;

&lt;p&gt;Each tool logs at that boundary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# _log.sh (sourced by every tool)&lt;/span&gt;
tlog&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c"&gt;# tlog &amp;lt;event&amp;gt; [detail]   event: INVOKED | OK | DRY | ERR&lt;/span&gt;
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s | %-12s | %-7s | %s\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%Y-%m-%dT%H:%M:%SZ&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; .sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;:2&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The log separates two questions that side effects conflate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... | notify | INVOKED | SIGNAL | Morning briefing   # the interface was called
... | notify | OK      | SIGNAL HTTP 200             # the implementation sent it
... | notify | DRY     | SIGNAL                      # called, but did not send (DRY_RUN)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;INVOKED&lt;/code&gt; records that the model used the tool, independent of any outcome; &lt;code&gt;OK&lt;/code&gt;/&lt;code&gt;DRY&lt;/code&gt;/&lt;code&gt;ERR&lt;/code&gt; records what the implementation did. Because the model depends on the interface rather than the implementation, the same routine can run in a &lt;strong&gt;shadow mode&lt;/strong&gt; — where &lt;code&gt;notify&lt;/code&gt; only logs and never sends — with no change in the model's behavior. The boundary log is also the reliable way to audit a past run: it records what executed, not merely what the skill instructed.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pattern, and its limit
&lt;/h2&gt;

&lt;p&gt;This is a pattern, not a framework — and that's its honest limit: &lt;strong&gt;nothing enforces it at runtime.&lt;/strong&gt; There's no base class, no inversion of control, nothing that &lt;em&gt;prevents&lt;/em&gt; a routine from ignoring its loadout or inlining raw mechanics again. Adherence is a matter of discipline — or, if you want a guardrail, a CI check that every skill carries a mission and a declared loadout. What you get in exchange is lightness: nothing to install, and incremental adoption — one tool, one routine at a time, in any stack that runs a script and a prompt.&lt;/p&gt;

&lt;p&gt;And one more honest note: this is a pattern I &lt;em&gt;believe&lt;/em&gt; I found, not a validated standard. If you know a better name — or earlier prior art — I'd genuinely like to hear it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;Go back to the suit. You upgrade the brain by adopting a better model — that's not code you write, it's a model you swap in. Your day-to-day engineering goes into the equipment: what the brain can discover, reach for, and be observed using. And because the brain depends on interfaces — a loadout of named tools — the suit is model-agnostic: change the model and the same loadout still fits. A self-describing, observable loadout is precisely how the brain &lt;em&gt;takes the wheel&lt;/em&gt;: it wakes, downloads the tools it's allowed, sees what it can do, and acts — and you can watch it do so at the interface, not by guessing from side effects. The system stops being a program that occasionally calls a model, and becomes a suit a capable model wears.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recipe (TL;DR)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt; = small scripts, one capability each, mechanics hidden — together, your toolbox. Add a &lt;code&gt;--describe&lt;/code&gt; line and a boundary log (&lt;code&gt;INVOKED&lt;/code&gt; + &lt;code&gt;OK/DRY/ERR&lt;/code&gt;). Side-effecting tools support a &lt;code&gt;DRY_RUN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loadout&lt;/strong&gt; = an assembler that prints a routine's named tools' self-descriptions. The routine runs it at wake to &lt;em&gt;download its loadout&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt; = mission (judgment) + a loadout list. No mechanics. Let the brain &lt;em&gt;compose&lt;/em&gt; tools; never auto-chain them in the wiring.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Runnable examples are in &lt;a href="https://github.com/bighaeil/agent-loadout-pattern/tree/main/examples" rel="noopener noreferrer"&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

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