<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Aaron]]></title><description><![CDATA[Aaron]]></description><link>https://www.aaronp.net</link><image><url>https://www.aaronp.net/img/substack.png</url><title>Aaron</title><link>https://www.aaronp.net</link></image><generator>Substack</generator><lastBuildDate>Mon, 06 Jul 2026 06:33:37 GMT</lastBuildDate><atom:link href="https://www.aaronp.net/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Aaron]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[aaron824205@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[aaron824205@substack.com]]></itunes:email><itunes:name><![CDATA[Aaron]]></itunes:name></itunes:owner><itunes:author><![CDATA[Aaron]]></itunes:author><googleplay:owner><![CDATA[aaron824205@substack.com]]></googleplay:owner><googleplay:email><![CDATA[aaron824205@substack.com]]></googleplay:email><googleplay:author><![CDATA[Aaron]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Can You Trust an LLM Judge?]]></title><description><![CDATA[Part 2 of 4 in the Local AI Code Review series]]></description><link>https://www.aaronp.net/p/can-you-trust-an-llm-judge</link><guid isPermaLink="false">https://www.aaronp.net/p/can-you-trust-an-llm-judge</guid><dc:creator><![CDATA[Aaron]]></dc:creator><pubDate>Sat, 04 Jul 2026 01:44:12 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f23c7bde-b916-4ff1-b66a-e294b39f2f75_1568x672.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Part 2 of 4 in the Local AI Code Review series</em></p><div><hr></div><p>The first article in this series introduced vet, a command-line tool that uses AI to generate code review issues and then validates each one against a six-question rubric before surfacing it to a developer [1]. That validation step represents a design pattern that appears across a growing range of AI systems. Understanding the pattern is what makes the model selection challenge in Parts 3 and 4 more than a benchmark exercise.</p><p>This article covers how the pattern works, why yes-bias is the most common and least obvious failure mode, and what properties to verify before trusting a candidate model.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.aaronp.net/subscribe?"><span>Subscribe now</span></a></p><h2>The Concept Defined</h2><p>A standard language model interaction is generative: a prompt goes in and the model produces a response. An LLM judge works differently. It receives a structured input comprising two elements, the artifact to evaluate and the criteria by which to evaluate the artifact, and returns a verdict. The output is not speculation, it is a judgment.</p><p>The judge is not generating new content. It is discriminating: valid or not, pass or fail, accurate or inaccurate. The distinction matters because the properties that make a model good at generation (fluency, creativity, coherent long-form reasoning) are not the same properties that make it reliable at judgment (consistency, rubric adherence, appropriate skepticism).</p><p>The judge can evaluate outputs from a larger model, a smaller model, or the same model class. The size relationship between the generator and the judge is not the relevant variable. What matters is whether the judge&#8217;s verdicts are reliable. In vet&#8217;s case, the generated code issue is the artifact, the six-question rubric from Part 1 is the criteria, and the verdict is a pass or fail. The pattern is the same regardless of the implementation.</p><h2>How It Works in Practice</h2><p>A judge call has three core components: the artifact, the rubric, and the verdict format.</p><p>The <strong>artifact</strong> is whatever is being evaluated. In a code review context, that is a generated issue alongside the diff that prompted it. In other contexts it might be a customer support response, a generated summary, or a piece of information extracted from a document.</p><p>The <strong>rubric</strong> is the set of explicit criteria that define what &#8220;valid&#8221; means for this particular task. In vet&#8217;s case, the rubric includes questions such as: &#8220;Is the issue grounded in specific code, rather than in the absence of something?&#8221; and &#8220;Is the flagged code actually being removed by this diff?&#8221; Each criteria targets a concrete failure mode rather than leaving the model to form a general response. A rubric written this way is auditable; any case where the judge returns the wrong answer can be traced back to specific criteria that was misapplied or misunderstood. This pattern of decomposing evaluation into fine-grained per-criterion binary decisions is well-established in LLM judge research, appearing independently in systems such as G-Eval and HD-Eval [2].</p><p>The <strong>verdict</strong> is the judge&#8217;s structured output: a boolean per criterion, a score, or a final pass/fail. The key word is structured. A judge that returns free-form language about quality is difficult to integrate into an automated pipeline. A judge that returns a predictable, machine-readable verdict can be wired directly into the system. In a minimal implementation, the output might be as simple as <code>{"valid": true, "criteria": [true, true, false, true, true, false]}</code>, one boolean per rubric question. That structure is what allows a downstream pipeline to act on the verdict without parsing natural language.</p><p>It is worth noting that rubric design is a form of engineering in its own right. A vague rubric produces vague, unreliable judgments. A rubric that can be tested against a labeled dataset, where the correct verdict is known in advance, is considerably more trustworthy than one built on intuition about what the model will do.</p><h2>Why It Matters: Scale and Consistency</h2><p>The appeal of an LLM judge is scale. Human review of every AI-generated output is impractical when generation runs on every commit, every query, or every customer interaction. A judge enables quality filtering to run automatically at the same speed as generation, without requiring human attention on each individual case.</p><p>A judge also applies the rubric consistently. A human reviewer working under time pressure may weight criteria differently from one review to the next. The judge applies exactly the same rubric to every artifact it sees.</p><p>Two failure modes carry equal weight. A judge that lets invalid outputs through, producing false positives, erodes trust in the overall system. With enough noise, users stop paying attention to the results. A judge that filters valid outputs, producing false negatives, reduces coverage and undermines the system&#8217;s purpose. Both matter, and a well-calibrated judge minimizes both.</p><p>It is also worth stating the appropriate scope: a judge is a filter, not a replacement for human judgment at decision points that carry real consequences.</p><h2>The Yes-Bias Problem</h2><p>The most common judge failure mode is not inaccuracy on a specific criterion. It is a pervasive tendency to return &#8220;pass&#8221; regardless of what the model receives. This is called yes-bias, and understanding why it happens is important before evaluating any candidate model.</p><p>Language models are trained through a process called reinforcement learning from human feedback (RLHF), which optimizes for outputs that human raters find agreeable and helpful. Research on LLM evaluators identifies this as the root cause of what the field calls self-enhancement bias: a structural tendency to return favorable verdicts regardless of whether the input merits them [2]. A judge role requires the opposite: selective rejection, skepticism toward plausible-looking artifacts, willingness to return &#8220;fail&#8221; even when the input seems reasonable at first glance. These behaviors run contrary to what RLHF training reinforces.</p><p>A yes-biased judge can appear, superficially, to be performing well. If most artifacts it receives happen to be valid, a model that says &#8220;pass&#8221; to everything will show a high accuracy score. The problem becomes visible only when the dataset is balanced, with roughly equal valid and invalid cases. On a balanced dataset, a yes-biased model scores approximately 50%, identical to random guessing [2]. That is the test that exposes the problem before it enters production.</p><p>Yes-bias is also not detectable from general benchmark scores. A model that performs well on reasoning tasks or code generation can still be yes-biased in a judge role on a specific rubric. The only reliable way to check is to run the model against labeled scenarios where the correct answer is &#8220;fail,&#8221; and observe whether it returns &#8220;fail.&#8221; In practice, a yes-biased model looks deceptively functional at first: the response format is correct, there are no errors, and verdicts appear considered. The problem only surfaces when the expected answers are checked against the actual output.</p><p>The practical implication is direct: checking for yes-bias should be the first step when evaluating a judge candidate, before prompt tuning or system message work. A model that cannot return &#8220;fail&#8221; on clear negative cases cannot be tuned into a reliable judge. It is worth noting that the opposite failure exists as well: a model that rejects nearly everything regardless of the input. That variant scores equally poorly on a balanced dataset and fails in the same way, just in the other direction. The goal is calibration, not skepticism for its own sake.</p><h2>What Makes a Reliable Judge</h2><p>With yes-bias in mind, the properties that distinguish a reliable judge become concrete.</p><p><strong>Determinism.</strong> At a fixed temperature setting, the same input should produce the same verdict on every call. A judge that returns different answers on identical scenarios introduces noise rather than removing it. Thus, benchmarking becomes unreliable and production behavior becomes unpredictable [2].</p><p><strong>Rubric adherence.</strong> The model should evaluate against the stated criteria, not drift toward a general impression of quality. A judge that ignores a specific criterion in favor of a holistic &#8220;this seems fine&#8221; response is not applying the rubric [2].</p><p><strong>Appropriate skepticism.</strong> The model should return &#8220;fail&#8221; when criteria are not met, even when the artifact looks plausible. This is the counterweight to yes-bias; a well-calibrated judge neither agrees with everything nor rejects everything.</p><p><strong>Bias resistance beyond yes-bias.</strong> Yes-bias is the most common failure mode, but research on LLM judge systems identifies several others that are directly relevant to a code review context: length bias, where a model favors verbose issue descriptions regardless of validity; concreteness bias, where specific line numbers or technical terminology cause an issue to pass even when the underlying claim is wrong; and position bias, where verdicts shift based on where content appears within the prompt [2]. A rubric-based judge is partially protected by its structured criteria, but these biases are worth verifying on a sample of known-verdict cases before a candidate is promoted for use.</p><p><strong>Context capacity.</strong> The judge receives the artifact plus the rubric and supporting context. On long inputs, a small context window risks truncation, which is particularly problematic because it is often silent: the model produces a verdict anyway, based on incomplete information. The practical countermeasures are straightforward; prefer models with a context window sized to the largest expected input, and keep the rubric concise so it does not consume a disproportionate share of available tokens.</p><p>All five of these properties are directly testable before deployment, and that is worth emphasizing. A small labeled evaluation dataset, even ten to fifteen representative scenarios with known correct verdicts, provides more reliable signal about judge performance than a general benchmark. Scores on standard capability benchmarks measure abilities that may not correspond to performance on a specific structured rubric in a specific domain. This is the practical entry point for evaluating a judge candidate: build the dataset first, run the candidate against it, and let the results guide every decision that follows.</p><p>Testing these properties fits well with my scenario. I have a structured rubric from vet to build a dataset with known answers. The judge candidate can then be validated against the artifact it generates, plus the rubric, and the dataset.</p><h2>What Comes Next</h2><p>The LLM judge is a pattern for systematic, scalable quality filtering of AI-generated output. Its reliability depends on a clear and testable rubric, determinism in the model&#8217;s responses, and resistance to known pitfalls. Those are the properties that separate a reliable judge from one that merely appears reliable. Understanding them concretely is what makes the model comparison ahead more than a ranking exercise; it shows which properties actually matter when the pattern has to work under real conditions.</p><p>Vet&#8217;s framework has these properties. The cost described in Part 1 [1], comes in the form of session token limits that make consistent coverage difficult on an active codebase. The question is whether a small, locally-run model can meet the same reliability bar without the per-call token spend.</p><p>Part 3 of this series examines the model landscape: what small language models are, why they are a reasonable fit for the judge role, and what properties to look for in the candidates selected for testing.</p><p>Stay tuned for the next article<em>: SLMs vs LLMs: Choosing a Model for Judgment Tasks</em></p><h2>References</h2><p>[1] <a href="https://open.substack.com/pub/aaron824205/p/what-is-an-llm-judge?r=lw363&amp;utm_campaign=post-expanded-share&amp;utm_medium=web">What is an LLM Judge?</a></p><p>[2] <a href="https://www.semanticscholar.org/paper/A-Survey-on-LLM-as-a-Judge-Gu-Jiang/e24424283c02fbe7f641e5b3490d7bb059f8355a?utm_source=direct_link">A Survey on LLM-as-a-Judge, arXiv:2411.15594v6</a></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://ko-fi.com/perezcreations" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qzIX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!qzIX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!qzIX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!qzIX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qzIX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png" width="201" height="54.948170731707314" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:984,&quot;resizeWidth&quot;:201,&quot;bytes&quot;:25538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://ko-fi.com/perezcreations&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/204996050?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qzIX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!qzIX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!qzIX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!qzIX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa4afa9-f5c5-455d-a61f-26d5e4c52bf6_984x269.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Buy me Coffee</figcaption></figure></div><p></p>]]></content:encoded></item><item><title><![CDATA[What Is an LLM Judge? ]]></title><description><![CDATA[How vet Uses It for Code Review]]></description><link>https://www.aaronp.net/p/what-is-an-llm-judge</link><guid isPermaLink="false">https://www.aaronp.net/p/what-is-an-llm-judge</guid><dc:creator><![CDATA[Aaron]]></dc:creator><pubDate>Mon, 29 Jun 2026 01:05:57 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b93700b8-b1dd-4deb-926f-9dc7d987bf26_1568x672.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Part 1 of 4 in the Local AI Code Review series</em></p><div><hr></div><p>When writing code with AI and Spec Driven Development (SDD), I have found that there are still mistakes in spite of good specs. No matter how detailed or concise the spec, things were missed. When searching for a way to have &#8220;self healing&#8221; reviews to validate implementations, I came across many methods. One of the methods that seemed to work better than others was a utility from imbue-ai call &#8220;verify everything&#8221; (vet) [1]. This utility used python scripts and LLM as a judge to review diffs and score them to validate the spec was implemented correctly.</p><p>After a few weeks of regular use, vet caught real issues: logic errors that would have slipped through, silent failure patterns buried in error-handling code, and missed tests. Not every flagged issue was valid, but the signal-to-noise ratio was good enough that running vet on every commit felt worth the overhead</p><p>Then the session limits started appearing.</p><p>Vet&#8217;s judgment step, which decides whether a flagged issue is actually worth surfacing, runs against a cloud LLM by default (Anthropic or OpenAi). However, vet can use the existing agent if the cloud provider is not available. Using cloud or agent API connection for a judge comes with tradeoffs. The most common is session token limits, which often stopps work once hit.</p><p>Rather than accepting the limit as a fixed constraint, the more interesting question was whether a locally-run model could serve as the judge, eliminate the session limits, and maintain the quality that made vet useful in the first place. This article covers what vet is, how its LLM judge step works, and why that architecture makes a local replacement worth exploring. That investigation is what this series documents.</p><div><hr></div><h2>The vet Pipeline: From Diff to Developer</h2><p>The flow from a code change to a surfaced issue passes through several stages. A developer commits code or opens a pull request. Vet&#8217;s issue identifiers analyze the diff and produce a set of candidate issues. Each candidate then passes through a judgment function that acts as a filter.</p><p>The judge receives four inputs: the unified diff, the commit message, the issue description, and a guide that defines what the issue type is meant to detect. It returns a verdict, pass or fail. Only issues that pass the verdict reach the developer.</p><p>The asymmetry here matters. False positives, invalid issues surfaced to the developer, erode trust over time. Enough noise and reviewers start dismissing vet&#8217;s output without reading it. False negatives, valid issues filtered out, reduce coverage and defeat the tool&#8217;s purpose. The system is calibrated to avoid false positives first, which means the judge is intentionally strict.</p><p>The token cost concentrates in the judgment step. Every candidate issue requires a separate call to the cloud LLM, with roughly 1,500 to 2,500 tokens of context per call. On an active codebase or large changes, this adds up quickly. The session limit is not a failure of the tool; it is the natural consequence of using a cloud API for every individual judgment call.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.aaronp.net/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>The Six-Question Rubric</h2><p>The judge does not form a general impression of whether an issue seems valid. It answers six specific yes-or-no questions, each targeting a distinct way an issue can be flawed.</p><p><strong>q1:</strong> Is the issue grounded in specific code, rather than in the absence of something? An issue that says &#8220;there is no input validation here&#8221; is flagging missing code, not a defect in the code that exists. This question filters out absence-of-information issues, which cannot be verified from the diff alone.</p><p><strong>q2:</strong> Does the issue avoid speculating about how code might be used, without evidence of that usage in the codebase? A concern like &#8220;this could be called with untrusted input&#8221; is speculation unless the code diff shows the actual function call. This question filters out issues that project hypothetical usage scenarios onto code the diff does not demonstrate being misused.</p><p><strong>q3:</strong> Is the severity reasonable? Does the issue warrant surfacing to a developer, or is it a trivially minor concern that adds noise without value?</p><p><strong>q4:</strong> Is the issue introduced by this diff pre-existing or not? An issue present in code that the diff didn&#8217;t touch is not something this commit caused; thus, surfacing is misleading.</p><p><strong>q5:</strong> Does the issue match its declared type? A <code>poor_naming</code> issue should describe a naming problem. A <code>logic_error</code> should describe incorrect logic. Type mismatches indicate the issue generator fired against the wrong category.</p><p><strong>q6:</strong> Is the flagged code actually being <em>removed</em> by this diff? In unified diff format, lines prefixed with a minus sign are being deleted by the commit. Flagging code that the developer is already in the process of removing is not a useful signal.</p><p>The pass condition is precise: all of q1 through q5 must be true, and q6 must be false. A single failure filters the issue out.</p><p>Q6 is the most diff-specific of the six. It requires the judge to understand unified diff format conventions, specifically that a &#8220;-&#8221; prefix marks code being deleted, not code that will exist in the final result. This detail is not universally internalized by language models from training alone, as this series will cover in a later part.</p><p>The rubric is what makes vet reliable. It forces the judge model to evaluate each failure mode independently rather than making a general judgement call. It also makes the judge LLM replaceable: the rubric is explicit and testable, which means any candidate model can be evaluated against it before being trusted.</p><div><hr></div><h2>Why the Session Limit Became a Design Problem</h2><p>Session limits are not a flaw in vet. They are the expected cost of delegating structured judgment to a cloud LLM at scale. The question they raise is whether that delegation is necessary.</p><p>The rubric is explicit. The task is narrow. The output is a structured verdict, not a generic description. These properties suggest that a judge does not necessarily require a frontier model. With Small Laguage Model (SLM) advancements in 2026, a smaller, locally-run model might handle q1 through q6 reliably, without session limits, without per-call token cost, and without sending large code diffs to an external API.</p><p>The practical appeal of a local judge is straightforward: consistent availability, and the ability to run on every commit without accumulating against a quota. The open question is whether &#8220;capable enough&#8221; is achievable at small scale. A local model that agrees with everything would solve the cost problem while undermining the quality guarantee entirely.</p><p>That question is worth investigating carefully. The rubric is explicit, the task is narrow, and the output is structured, which suggests the judgment step does not inherently require a frontier model. Whether a small local model can meet that bar is not obvious, and the answer turns on failure modes that are easy to overlook. Part 2 of this series [2] introduces the LLM judge concept in full, including the yes-bias, the failure mode that makes model selection more nuanced than it first appears. The story started with a tool that worked well enough to trust and a cost structure that made consistent use impractical. Whether a small model can preserve what made it worth trusting is the question this series sets out to answer.</p><h2>References</h2><p>[1] <a href="https://github.com/imbue-ai/vet">https://github.com/imbue-ai/vet</a></p><p>[2] <a href="https://open.substack.com/pub/aaron824205/p/can-you-trust-an-llm-judge?r=lw363&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=true">Can You Trust an LLM Judge?</a></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://ko-fi.com/perezcreations" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lIjj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!lIjj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!lIjj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!lIjj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lIjj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png" width="201" height="54.948170731707314" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:984,&quot;resizeWidth&quot;:201,&quot;bytes&quot;:25538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://ko-fi.com/perezcreations&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/204041972?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lIjj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!lIjj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!lIjj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!lIjj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F871533ab-4f7f-43b3-848e-c9eea733987b_984x269.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Buy me Coffee</figcaption></figure></div><p></p>]]></content:encoded></item><item><title><![CDATA[Kiro Sub-Agent Patterns]]></title><description><![CDATA[Which one do you choose?]]></description><link>https://www.aaronp.net/p/kiro-sub-agent-patterns</link><guid isPermaLink="false">https://www.aaronp.net/p/kiro-sub-agent-patterns</guid><dc:creator><![CDATA[Aaron]]></dc:creator><pubDate>Tue, 16 Jun 2026 03:28:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!y-pj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y-pj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y-pj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 424w, https://substackcdn.com/image/fetch/$s_!y-pj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 848w, https://substackcdn.com/image/fetch/$s_!y-pj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 1272w, https://substackcdn.com/image/fetch/$s_!y-pj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y-pj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png" width="1424" height="752" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:752,&quot;width&quot;:1424,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1994993,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/202223501?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y-pj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 424w, https://substackcdn.com/image/fetch/$s_!y-pj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 848w, https://substackcdn.com/image/fetch/$s_!y-pj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 1272w, https://substackcdn.com/image/fetch/$s_!y-pj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadf3186-4849-44d8-9ac5-7008500e3d34_1424x752.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The intuition behind using multi-agents or sub-agents with Kiro is straightforward: more agents working in parallel means faster output. It is a reasonable assumption, and Kiro makes it easy to act on. As of version 0.8, Kiro supports synchronous sub-agents across the IDE, CLI, and ACP clients. Kiro agents can also invoke other agents, giving you access to two common multi-agent topologies that fit the majority of needs [1]. However, picking the right topology pattern is less about capability and more about understanding where each pattern breaks down. A 2026 research paper makes the failure mode precise, and the number is worth knowing before you split a task across multiple agents [2].</p><h2>Two Patterns, Two Trade-offs</h2><p>Kiro includes the <strong>Maker-Evaluator</strong> sub-agent topology by default, with <strong>Hub-and-Spoke</strong> easily accessible [1]. Both are well-suited to specific tasks, but neither is a general-purpose upgrade over a single agent.</p><p><strong>Maker-Evaluator</strong> is a two-node loop: one agent produces output, a second evaluates it. When the same agent plays both roles, the pattern is called reflection. The main agent spawns a sub-agent and is blocked until the sub-agent completes. The main agent then decides whether to re-invoke based on the evaluation result.</p><p>This pattern fits iterative quality work: code review, coder-plus-tester automated turns, document generation with a writer-editor pair, and security auditing. Its token cost does not compound across iterations the way Hub-and-Spoke does across spokes, and failure recovery is simpler because the loop state is centralized.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!datD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!datD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 424w, https://substackcdn.com/image/fetch/$s_!datD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 848w, https://substackcdn.com/image/fetch/$s_!datD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 1272w, https://substackcdn.com/image/fetch/$s_!datD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!datD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png" width="1456" height="562" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:562,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1083222,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/202223501?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!datD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 424w, https://substackcdn.com/image/fetch/$s_!datD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 848w, https://substackcdn.com/image/fetch/$s_!datD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 1272w, https://substackcdn.com/image/fetch/$s_!datD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4adf3518-b54a-4215-85e5-2b689c91770b_1657x640.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Two failure modes are worth calling out before you wire up this pattern.</p><p><strong>1. Runaway loop.</strong> Without a termination condition, the loop will not stop on its own. The best mitigation is a hard iteration cap of three turns.</p><p><strong>2. Quality degradation.</strong> Quality gains flatten after roughly three turns, which Sartori&#8217;s research explains directly [2]. Using an adversarial evaluator with explicit, written rejection criteria and a defined standard rather than an implicit one will help maintain quality.</p><p><strong>Hub-and-Spoke</strong> is a star topology where one central hub agent decomposes a task, delegates subtasks to up to four spoke agents, and aggregates their results. Spokes do not communicate with each other in this topology. The hub holds the full picture; spokes operate in isolation.</p><p>This pattern works well where tasks are genuinely independent: a planner agent decomposing requirements, a coder agent implementing them, a tester agent validating the output. It also suits orchestrator-plus-specialist setups where each spoke owns a distinct domain.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BSXL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BSXL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 424w, https://substackcdn.com/image/fetch/$s_!BSXL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 848w, https://substackcdn.com/image/fetch/$s_!BSXL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 1272w, https://substackcdn.com/image/fetch/$s_!BSXL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BSXL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png" width="426" height="379.01185050136735" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:976,&quot;width&quot;:1097,&quot;resizeWidth&quot;:426,&quot;bytes&quot;:1758352,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/202223501?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BSXL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 424w, https://substackcdn.com/image/fetch/$s_!BSXL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 848w, https://substackcdn.com/image/fetch/$s_!BSXL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 1272w, https://substackcdn.com/image/fetch/$s_!BSXL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333dd8b3-3898-4849-94a7-91eeadf066da_1097x976.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The costs for this topology are real and compound quickly. The hub is a single point of failure: if it loses context or produces a malformed delegation, the entire workflow stalls. Kiro credit costs also accumulate across every spoke independently and count toward your total usage in parallel. Those sub-agent spokes are not free. File writes are a concern when multiple spokes write to the same files, causing collisions.</p><p>Three mitigation strategies are worth building in from the start.</p><p><strong>1. Accommodate parallel writes.</strong> Git Worktrees isolate parallel write paths so spokes do not overwrite each other&#8217;s changes, at the cost of disk space.</p><p><strong>2. Optimize inter-agent communication.</strong> Terse hub-to-spoke messages, sometimes called caveman mode, can reduce token overhead.</p><p><strong>3. Use persistent external memory.</strong> A &#8220;Document As You Go&#8221; pattern of structured session logs gives agents access to shared context that would otherwise be lost between invocations.</p><h2>The Multi-Agent Coordination Gap</h2><p>Think of two developers building the same feature in separate rooms with no way to talk to each other. Even with a perfect written spec, they will make small, incompatible decisions: one uses a list, the other uses a dictionary. Merging their work is harder than if one person had built the whole thing.</p><p>This is precisely what Sartori 2026 [2] set out to measure, and the results may surprise you. With a full specification, a single agent succeeded 89% of the time. Two agents working in parallel succeeded only 58%. With almost no specification at all, the single agent dropped to 56%, and the two-agent split dropped to 25%. The gap never closed, regardless of how detailed the spec was.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Kovv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Kovv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 424w, https://substackcdn.com/image/fetch/$s_!Kovv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 848w, https://substackcdn.com/image/fetch/$s_!Kovv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 1272w, https://substackcdn.com/image/fetch/$s_!Kovv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Kovv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png" width="1408" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1408,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1060915,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/202223501?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Kovv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 424w, https://substackcdn.com/image/fetch/$s_!Kovv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 848w, https://substackcdn.com/image/fetch/$s_!Kovv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 1272w, https://substackcdn.com/image/fetch/$s_!Kovv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8c15aca-5ed2-43dc-b71f-182c3210180c_1408x768.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A better spec helps both approaches equally. It does not close the gap between them. The 25-to-39 percentage point penalty is structural: it comes from the agents not sharing decisions, not from the quality of the instructions.</p><p>This is why the Maker-Evaluator loop has a ceiling around three turns. Every additional iteration is two agents coordinating again, each time incurring that same overhead. More turns do not compound quality; they compound cost.</p><h2>The Decision</h2><p>Think of pattern selection as a per-task trade-off rather than a project-wide default.</p><p>Hub-and-Spoke is the right choice when tasks are genuinely independent, when parallelism matters more than accuracy on any individual task, and when the hub can synthesize partial outputs without needing agents to share state. If those conditions are not met, you absorb the coordination penalty without the parallelism benefit.</p><p>Maker-Evaluator is the right choice when iterative quality improvement is the goal, when the iteration count is bounded at three turns, and when the evaluator is independent of the implementor. An evaluator agent that shares context with the implementor absorbs the full coordination gap without providing independent verification.</p><p>A single agent remains the right choice when the task requires shared context across steps, when the codebase contains implicit invariants that agents cannot reliably infer, or when correctness is the primary constraint and the coordination penalty is unacceptable.</p><p>Three practical anchors apply regardless of which pattern you choose. Kiro allows custom agent definitions that specify model, tools, and context per sub-agent; use this to constrain scope rather than expand it. The intent document, or steering file, is the only persistent state between stateless agent sessions; without it, context resets on every invocation. For Maker-Evaluator specifically, write the termination condition before you wire the loop, because the model will not determine when enough is enough on its own.</p><p>Multi-agent is not a free upgrade. Hub-and-Spoke trades accuracy per task for parallelism. Maker-Evaluator trades compounding latency and a hard quality ceiling for iterative improvement. Sartori&#8217;s data makes the cost explicit: 25 to 39 percentage points of coordination overhead, present at every specification level, recoverable only by concentrating context in a single agent [2]. Knowing when not to split is the decision that makes the other two patterns worthwhile.</p><h2>Ready? <a href="https://aaron824205.substack.com/p/aws-kiro-custom-agents-your-first">Build your first Kiro Agent in 15 Minutes</a> </h2><h1>References</h1><p>[1] J. Wasowski, <em>After Analyzing 17 Multi-Agent Topologies - 7 Anti-Patterns That will Burn Your Budget</em>, 2026 <a href="https://medium.com/gitconnected/after-analyzing-17-multi-agent-topologies-7-anti-patterns-that-will-burn-your-budget-28cc6909621c">https://medium.com/gitconnected/after-analyzing-17-multi-agent-topologies-7-anti-patterns-that-will-burn-your-budget-28cc6909621c</a></p><p>[2] C. Sartori, <em>The Specification Gap: Coordination Failure Under Partial Knowledge in Code Agents</em>, 2026 <a href="https://doi.org/10.48550/arXiv.2603.24284">https://doi.org/10.48550/arXiv.2603.24284</a></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://ko-fi.com/perezcreations" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WV4f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!WV4f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!WV4f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!WV4f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WV4f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png" width="241" height="65.88313008130082" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:984,&quot;resizeWidth&quot;:241,&quot;bytes&quot;:25538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://ko-fi.com/perezcreations&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/202223501?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WV4f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!WV4f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!WV4f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!WV4f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d95e4e-fa66-4d32-b49d-d6dbaeb2da8d_984x269.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Buy me Coffee</figcaption></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Sandboxing Kiro CLI]]></title><description><![CDATA[A Developer's Guide to Safe AI Agent Execution]]></description><link>https://www.aaronp.net/p/sandboxing-kiro-cli</link><guid isPermaLink="false">https://www.aaronp.net/p/sandboxing-kiro-cli</guid><dc:creator><![CDATA[Aaron]]></dc:creator><pubDate>Mon, 08 Jun 2026 22:59:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!e46I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e46I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e46I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 424w, https://substackcdn.com/image/fetch/$s_!e46I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 848w, https://substackcdn.com/image/fetch/$s_!e46I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 1272w, https://substackcdn.com/image/fetch/$s_!e46I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e46I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png" width="776" height="466" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:466,&quot;width&quot;:776,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:105037,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/200067132?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e46I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 424w, https://substackcdn.com/image/fetch/$s_!e46I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 848w, https://substackcdn.com/image/fetch/$s_!e46I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 1272w, https://substackcdn.com/image/fetch/$s_!e46I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F607875ca-fb1d-43b8-9659-e8ff3de0db04_776x466.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When an AI agent like Kiro executes commands, modifies files, or runs scripts, it does so with whatever permissions your local environment provides. For workflows involving sensitive data, production credentials, or complex automation, this introduces meaningful risk. Sandboxing defines explicit boundaries around what Kiro can and cannot do, reducing that risk without sacrificing productivity.</p><p>This guide is written for developers using Kiro on macOS. It covers what sandboxing is, why it matters, and three practical methods for applying it to your workflow.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3><strong>Table of Contents</strong></h3><ul><li><p>What Is Sandboxing?</p></li><li><p>Why Sandboxing Is Needed</p></li><li><p>Can Hooks Replace a Sandbox?</p></li><li><p>How to Sandbox Kiro on macOS</p></li><li><p>Feature Comparison</p></li><li><p>Advantages of Sandboxing</p></li><li><p>Limitations of Sandboxing</p></li><li><p>Conclusion</p></li></ul><h2><strong>What Is Sandboxing?</strong></h2><p>Sandboxing means running an AI agent, or the commands it issues, inside a restricted and isolated environment. The agent retains the ability to perform actions, but only within carefully controlled boundaries.</p><p>Consider the analogy of a workshop with a locked tool cabinet. A craftsperson can work freely within the workshop, using whatever tools are available, but cannot access anything locked away or work outside the designated space. Kiro operates in a similar fashion: it can execute commands, modify files, and run scripts, but only within the limits you define.</p><div><hr></div><h2><strong>Why Sandboxing Is Needed</strong></h2><p>Without defined boundaries, an AI agent operates with the same access rights as the developer running it. In practice, this means it could accidentally:</p><ul><li><p>delete important files</p></li><li><p>expose API keys or credentials stored in shell profiles</p></li><li><p>damage the operating system</p></li><li><p>modify files outside the intended project scope</p></li><li><p>access private data stored elsewhere on disk</p></li></ul><p>Consider a command as simple as:</p><pre><code><code>rm -rf /</code></code></pre><p>Without restrictions, this would destroy an entire macOS system. Sandboxing prevents this class of accident by restricting what the agent is permitted to touch before any command executes.</p><p>To see this in practice: suppose Kiro needs to run <code>python app.py</code>. With sandboxing, execution is constrained to <code>/home/user/project</code>. It cannot reach system folders, modify directories outside the project, or read sensitive files elsewhere. The operation completes normally, but the damage from any mistake is contained.</p><div><hr></div><h2><strong>Can Hooks Replace a Sandbox?</strong></h2><p>Kiro supports hooks, which are rules that inspect and can block actions before they are executed. A common question is whether hooks provide sufficient security on their own. The short answer is: they help, but they are not a substitute.</p><p>A useful way to frame the distinction is:</p><ul><li><p>Hooks are specific checks</p></li><li><p>A sandbox is the boundary itself</p></li></ul><p>Hooks work by inspecting commands, checking for dangerous patterns, and allowing or blocking behavior accordingly. They are a valuable layer of defense. However, hooks are implemented in software and carry the same vulnerabilities as any software system. If a hook fails to match the exact command invocation used, the command proceeds. A sandbox restricts access at the environment level regardless; the operating system enforces the boundary, not the hook.</p><p>Hooks and sandboxing are complementary, not competing. Hooks provide targeted checks; sandboxes provide the hard boundary that catches what hooks miss.</p><div><hr></div><h2><strong>How to Sandbox Kiro CLI on macOS</strong></h2><p>There are three primary approaches, each suited to a different level of isolation and workflow complexity.</p><h3><strong>1. Use a Virtual Machine (UTM)</strong></h3><p>A virtual machine (VM) provides the most complete form of isolation available. It creates an entirely separate macOS environment, with its own kernel, filesystem, and user profile, running as a guest on your physical machine. Kiro, installed inside the VM, has no visibility into your host machine&#8217;s files, credentials, or shell configuration.</p><p>For macOS on Apple Silicon, <a href="https://mac.getutm.app/">UTM</a> is the recommended choice. It is free, and well-suited to running macOS guest environments.</p><p><strong>Setup steps:</strong></p><ol><li><p>Download and install UTM from the official site (<a href="https://mac.getutm.app/">mac.getutm.app</a>) or from the Mac App Store.</p></li><li><p>Open UTM and select <em>Virtualize</em> from the start screen.</p></li><li><p>Choose <em>macOS 12+</em> as the operating system.</p></li><li><p>Import or download the macOS installer. If UTM offers the option to continue without selecting an IPSW file, it will use the installer on your boot partition.</p></li><li><p>Set RAM and CPU limits appropriate to your host machine.</p></li><li><p>Set a disk size for the virtual environment.</p></li><li><p>Review and save the configuration on the Summary screen. The VM will appear in the left sidebar.</p></li><li><p>Launch the VM using the play button. Initial setup will take several minutes to complete.</p></li></ol><p>Once the guest environment is running and <code>kiro-cli</code> is installed inside it, the agent operates in complete isolation. Your host machine&#8217;s <code>Documents</code> folder, <code>Desktop</code>, credentials, and shell profiles remain invisible to it.</p><h3><strong>2. Use a Container (Docker)</strong></h3><p>Docker containers offer a lighter-weight alternative to a full VM. They share the host macOS kernel but isolate the filesystem, processes, and network from the host environment. If a script runs incorrectly inside the container, only the container is affected; the host machine remains unchanged.</p><p><strong>Setup steps:</strong></p><ol><li><p>Create a <code>Dockerfile</code>:</p></li></ol><pre><code><code>FROM node:lts-slim
RUN apt-get update &amp;&amp; apt-get install -y git curl python3 build-essential
WORKDIR /workspace
RUN curl -fsSL https://cli.kiro.dev/install | bash</code></code></pre><ol start="2"><li><p>Build and tag the image:</p></li></ol><pre><code><code>docker build -f Dockerfile -t kiro-sandbox .</code></code></pre><ol start="3"><li><p>Start the container, mounting only the specific project directory Kiro should access:</p></li></ol><pre><code><code>docker run -it --rm \
  -v $(pwd):/workspace \
  kiro-sandbox bash</code></code></pre><h3><strong>3. Use Application-Level Isolation (SRT)</strong></h3><p>For developers who prefer to work directly on their local machine without a VM or container, application-level isolation provides a practical middle ground. <a href="https://github.com/anthropic-experimental/sandbox-runtime">Anthropic&#8217;s Sandbox Runtime</a> (<code>srt</code>) wraps <code>kiro-cli</code> in a declarative sandbox, enforcing filesystem and network boundaries using Apple&#8217;s native Seatbelt security framework on macOS.</p><p>It&#8217;s worth noting that <code>srt</code> is an experimental tool. Its configuration and API may evolve over time.</p><p><strong>Setup steps:</strong></p><ol><li><p>Install the Sandbox Runtime via npm:</p></li></ol><pre><code><code>npm install -g @anthropic-ai/sandbox-runtime</code></code></pre><ol start="2"><li><p>Create the configuration file at <code>~/.srt-settings.json</code>. The paths listed under <code>allowWrite</code> must include the application&#8217;s data directory, or the tool will not start correctly:</p></li></ol><pre><code><code>{
  "allowPty": true,
  "enableWeakerNestedSandbox": true,
  "enableWeakerNetworkIsolation": true,
  "network": {
    "allowedDomains": [
      "*.kiro.dev",
      "*.amazonaws.com",
      "*.awsapps.com",
      "*.aws.dev"
    ]
  },
  "filesystem": {
    "allowWrite": [
      "./workspace",
      "~/Library/Application Support/kiro-cli/",
      "~/.kiro"
    ]
  }
}</code></code></pre><ol start="3"><li><p>Launch <code>kiro-cli</code> inside the sandbox:</p></li></ol><pre><code><code>srt kiro-cli chat</code></code></pre><p>On macOS, <code>srt</code> hooks into Apple&#8217;s Seatbelt framework to enforce these boundaries at the kernel level. Any attempt by Kiro to write outside the <code>allowWrite</code> list or reach an unlisted domain is blocked before it executes.</p><div><hr></div><h2><strong>Feature Comparison</strong></h2><p>The three approaches differ not just in setup complexity, but in where the isolation boundary sits in the computing stack. The table below compares them across eight technical dimensions.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/ZRgM5/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a0c9a2ab-4494-4699-9bb8-23180d048631_1220x2788.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/19827b82-b890-419b-8442-316d40920389_1220x2788.png&quot;,&quot;height&quot;:1106,&quot;title&quot;:&quot;Created with Datawrapper&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/ZRgM5/1/" width="730" height="1106" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><div><hr></div><h2><strong>Advantages of Sandboxing</strong></h2><ul><li><p><strong>Blast Radius Containment:</strong> If something goes wrong, damage is confined to the sandbox; the host machine is unaffected and the sandbox can simply be discarded.</p></li><li><p><strong>Secure Execution of Untrusted Code:</strong> Safely test unfamiliar scripts or third-party tools without auditing every line in advance.</p></li><li><p><strong>Protection Against Zero-Day Exploits:</strong> Restricting what an application is permitted to do limits potential damage from vulnerabilities that have not yet been disclosed or patched.</p></li><li><p><strong>Clean, Reproducible Environments:</strong> Each instance starts from a known state, free of stale configuration or leftover artifacts from previous sessions.</p></li></ul><div><hr></div><h2><strong>Limitations of Sandboxing</strong></h2><ul><li><p><strong>Performance and Resource Overhead:</strong> Isolation boundaries require computational resources. Virtual machines in particular introduce meaningful CPU, RAM, and startup time costs that may affect developer experience.</p></li><li><p><strong>Sandbox Escape Vulnerabilities:</strong> No isolation mechanism is perfect. A flaw in the sandbox implementation can allow a process to break containment. External data sources, such as repositories containing hidden Unicode payloads, represent a less obvious escape vector.</p></li><li><p><strong>Context Blindness and Friction:</strong> The sandbox may block Kiro&#8217;s access to local files or internal tools it legitimately needs. Some configuration is necessary to restore that access without reopening the boundaries the sandbox is meant to enforce.</p></li><li><p><strong>Sandbox-Aware Behavior:</strong> Some malicious software detects when it is running inside a test environment and suppresses its harmful behavior, only revealing itself once it reaches an unrestricted host.</p></li><li><p><strong>Trusted-Channel Data Poisoning:</strong> Allowlisting domains like <code>github.com</code> or <code>google.com</code> grants network access but cannot sanitize the content returned. A prompt injection payload in a repository file, or adversarially crafted search results, can manipulate Kiro&#8217;s behavior from within the sandbox. The boundary controls what the agent can reach, not what it reads or how it interprets that content.</p></li><li><p><strong>No Defense Against Agentic Attack Vectors:</strong> Sandboxing operates at the system and network level and does not address the behavioral attack surface of an AI agent. The <a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP Top 10 for LLM Applications</a> identifies risks sandboxing cannot mitigate: goal hijacking, tool misuse, identity abuse, unexpected code execution, and context poisoning. These attacks target model reasoning, not the host OS, and pass through sandbox boundaries undetected.</p></li></ul><div><hr></div><h2><strong>Conclusion</strong></h2><p>Sandboxing controls what Kiro can access at the system and network level; it does not govern how the agent reasons about or responds to the content it retrieves. For macOS developers, the three approaches covered here represent a progression from maximum isolation to minimum friction.</p><ul><li><p>A <strong>virtual machine</strong> is the right choice when the risk profile demands the strongest possible guarantee, such as working with sensitive data or long-running agents.</p></li><li><p>A <strong>container</strong> is a sensible default for most development work, offering solid isolation with familiar tooling and low overhead.</p></li><li><p><strong>Application-level isolation</strong> via <code>srt</code> is well-suited to developers who need to stay close to their local environment while still enforcing meaningful boundaries around what Kiro can access.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://ko-fi.com/perezcreations" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pM2_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!pM2_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!pM2_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!pM2_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pM2_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png" width="239" height="65.33638211382114" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:984,&quot;resizeWidth&quot;:239,&quot;bytes&quot;:25538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://ko-fi.com/perezcreations&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/200067132?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pM2_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!pM2_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!pM2_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!pM2_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab572c5f-b375-4c54-9262-8e6896f79f39_984x269.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Buy me Coffee</figcaption></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[AWS Kiro Custom Agents: Your First Agent in 15 Minutes]]></title><description><![CDATA[A hands-on tutorial for building a custom agents]]></description><link>https://www.aaronp.net/p/aws-kiro-custom-agents-your-first</link><guid isPermaLink="false">https://www.aaronp.net/p/aws-kiro-custom-agents-your-first</guid><dc:creator><![CDATA[Aaron]]></dc:creator><pubDate>Sun, 24 May 2026 17:52:01 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0919eb07-6eb1-4406-b45a-9512005ab23f_1100x201.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BS7y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BS7y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 424w, https://substackcdn.com/image/fetch/$s_!BS7y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 848w, https://substackcdn.com/image/fetch/$s_!BS7y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 1272w, https://substackcdn.com/image/fetch/$s_!BS7y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BS7y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png" width="1100" height="201" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:201,&quot;width&quot;:1100,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52056,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/198966630?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BS7y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 424w, https://substackcdn.com/image/fetch/$s_!BS7y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 848w, https://substackcdn.com/image/fetch/$s_!BS7y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 1272w, https://substackcdn.com/image/fetch/$s_!BS7y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7f2d09a-32dc-4801-bd3c-b8ceb39de3d1_1100x201.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Kiro CLI ships with a default agent (kiro_default), but custom agents let you go further. A custom agent is a named configuration that gives an LLM a specific role, a defined set of tools, and context loaded automatically at startup. Rather than repeating the same prompt setup every session, a custom agent captures it once and makes it instantly available to you and your team.</p><p>This tutorial will walk through building a <code>code-reviewer</code> agent to review code with controlled tool access and automatically load a project README on startup. By the end, you will have a working local agent file you can activate, swap to, and commit to version control.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>What you will build:</strong> a <code>code-reviewer</code> agent that reads files and runs shell commands without prompting, loads your project README automatically, and greets you when activated.</p><p><strong>Time:</strong> ~15 minutes</p><h2>Prerequisites</h2><ul><li><p><a href="https://kiro.dev/cli">Kiro CLI</a> installed and authenticated (version &gt;= 2.1)</p></li><li><p>An active chat session (<code>kiro-cli chat</code>)</p></li><li><p>A project directory with a <code>README.md </code>under version control (git)</p></li></ul><div><hr></div><h2>Step 1 &#8212; Understand where agents live</h2><p>Kiro looks for agents in two places:</p><p>Location</p><ul><li><p><code>.kiro/agents/</code> in your project &#8212; Scope: only available for the project</p></li><li><p><code>~/.kiro/agents/</code> &#8212; Scope: available everywhere</p></li></ul><p>When both locations contain an agent with the same name, the local version takes precedence. This makes local agents a good choice when you want behavior tailored to a specific project, while global agents are better suited for general-purpose assistants you reach for everywhere.</p><p>For this tutorial, a <em><strong>local</strong></em> agent keeps things contained to your project.</p><p>To begin, create the agents directory in the project:</p><pre><code><code>mkdir -p .kiro/agents</code></code></pre><p>With the directory in place, the next step is creating the configuration file.</p><div><hr></div><h2>Step 2 &#8212; Create the agent file</h2><p>Create <code>.kiro/agents/code-reviewer.json </code>with the following content:</p><pre><code><code>{
  "name": "code-reviewer",
  "description": "Reviews code changes. Reads files and runs git commands without prompting.",
  "prompt": "You are a thorough code reviewer. Focus on correctness, clarity, and security. Be concise.",
  "tools": ["read", "shell"],
  "allowedTools": ["read", "shell"],
  "resources": [
    "file://README.md"
  ],
  "welcomeMessage": "Ready to review. Share a file path or paste a diff."
}</code></code></pre><p>What each field does:</p><ul><li><p><code>tools</code> &#8212; declares what the agent <em>can</em> use</p></li><li><p><code>allowedTools</code> &#8212; declares what runs <em>without a permission prompt</em></p></li><li><p><code>resources</code> &#8212; files loaded into context when the agent starts</p></li><li><p><code>welcomeMessage</code> &#8212; shown when you switch to this agent</p></li></ul><p>Save the file. Kiro detects new agent files automatically, no restart is required for the agent to appear in the list</p><p> <strong>Note on config changes:</strong> adding a new agent file takes effect immediately. Changes to an <em><strong>existing</strong></em> agent&#8217;s configuration, however, take effect the next time you activate the agent (via <code>/agent</code> swap). A running session does not reload mid-conversation.</p><div><hr></div><h2>Step 3 &#8212; Activate the agent</h2><p>Start a chat session:</p><pre><code><code>kiro-cli chat</code></code></pre><p>Inside the session, swap to your new agent:</p><pre><code><code> /agent</code></code></pre><p>Select <code>code-reviewer</code> from the list. You will see:</p><pre><code><code>&#10004; Choose one of the following agents &#183; code-reviewer
Ready to review. Share a file path or paste a diff.
code-reviewer &#183; auto</code></code></pre><p>Your <code>README.md</code> is already loaded in context. To confirm, ask the agent something about it:</p><pre><code><code>code-reviewer &#183; auto
What does this project do?</code></code></pre><p>The agent answers using the README content. No file-reading prompt appears because <code>read</code> is in <code>allowedTools</code> and runs silently by design.</p><div><hr></div><h2>Step 4 &#8212; Test tool permissions</h2><p>To see the permission boundary in action, ask the agent to inspect recent changes:</p><pre><code><code>code-reviewer &#183; auto 
What files have changed?</code></code></pre><p>The agent runs <code>git status</code> without prompting, because <code>shell</code> is pre-approved within <code>allowedTools</code>. Now try something outside its approved list:</p><pre><code><code>code-reviewer &#183; auto 
Write a summary to NOTES.md</code></code></pre><p>Kiro will prompt you for permission before writing, because <code>write</code> is not listed in <code>allowedTools</code>. This is the security boundary working as intended.</p><div><hr></div><h2>Step 5 &#8212; Restrict write access with toolsSettings</h2><p>You decide the agent <em>should</em> be able to write, but only to a <code>reviews/</code> directory. Exit Kiro and update the config to add <code>write</code> capability to both <code>tools</code> and <code>allowedTools</code>:</p><pre><code><code>{
  "name": "code-reviewer",
  "description": "Reviews code changes. Reads files and runs git commands without prompting.",
  "prompt": "You are a thorough code reviewer. Focus on correctness, clarity, and security. Be concise.",
  "tools": ["read", "write", "shell"],
  "allowedTools": ["read", "shell", "write"],
  "toolsSettings": {
    "write": {
      "allowedPaths": ["reviews/**"]
    }
  },
  "resources": [
    "file://README.md"
  ],
  "welcomeMessage": "Ready to review. Share a file path or paste a diff."
}</code></code></pre><p>Create the directory:</p><pre><code><code>mkdir reviews</code></code></pre><p>Start a new session with <code>kiro-cli chat</code> (config changes take effect on next chat activation), and swap to the code-review agent with commands from Step 3:</p><pre><code><code># activate new session
kiro-cli chat
# activate the code-review agent
/agent</code></code></pre><p>Now ask the agent to write a review:</p><pre><code><code>code-reviewer &#183; auto 
Review project files and save findings to reviews/main-review.md</code></code></pre><p>The agent writes to <code>reviews/main-review.md</code> without prompting. An attempt to write anywhere else will still require confirmation.</p><div><hr></div><h2>Troubleshooting</h2><h4>Agent does not appear in the <code>/agent</code> list</h4><p>Check that the file is valid JSON &#8212; a missing comma or bracket will silently prevent the agent from loading. A JSON linter or <code>jq . .kiro/agents/code-reviewer.json </code>can surface syntax errors quickly.</p><h4>Resource file not found warning</h4><p>Kiro resolves <code>file://</code> paths relative to the project root. If README is in a subdirectory, update the path to match: <code>file://docs/REAME.md</code></p><h4>Config changes not taking effect</h4><p>Changes to an existing agent require re-activation. Run <code>/agent</code> to change agents and then swap back to reload the config in the current session.</p><div><hr></div><h2>Conclusion</h2><ul><li><p>Agent files live in <code>.kiro/agents/</code> (local) or <code>~/.kiro/agents/</code> (global)</p></li><li><p><code>tools</code> declares availability; <code>allowedTools</code> removes the permission prompt</p></li><li><p><code>toolsSettings</code> constrains what allowed tools can touch (e.g., <code>allowedPaths</code> for <code>write</code> operations)</p></li><li><p><code>resources</code> pre-load files into context at startup</p></li></ul><h2>Next steps</h2><ul><li><p>Move the <code>prompt</code> to a separate file: <code>"prompt": "file://./prompts/code-reviewer.md"</code> for easier editing</p></li><li><p>Commit <code>.kiro/agents/code-reviewer.json</code> to version control so teammates get the same agent automatically</p></li><li><p>Read the official <a href="https://kiro.dev/docs/cli/custom-agents/configuration-reference/">configuration reference</a> for all available fields</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://ko-fi.com/perezcreations" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!odwO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!odwO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!odwO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!odwO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!odwO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png" width="239" height="65.33638211382114" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f856a96-a1fd-471c-893e-e10461806353_984x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:984,&quot;resizeWidth&quot;:239,&quot;bytes&quot;:25538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://ko-fi.com/perezcreations&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/198966630?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!odwO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!odwO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!odwO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!odwO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f856a96-a1fd-471c-893e-e10461806353_984x269.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Buy me Coffee</figcaption></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.aaronp.net/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[AI in the SDLC]]></title><description><![CDATA[What everyone overlooks]]></description><link>https://www.aaronp.net/p/ai-in-the-sdlc</link><guid isPermaLink="false">https://www.aaronp.net/p/ai-in-the-sdlc</guid><dc:creator><![CDATA[Aaron]]></dc:creator><pubDate>Fri, 15 May 2026 02:33:32 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/2ba0c3ac-2b4e-4705-bd6b-7dce4f89ee9d_273x214.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ns6h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ns6h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 424w, https://substackcdn.com/image/fetch/$s_!Ns6h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 848w, https://substackcdn.com/image/fetch/$s_!Ns6h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 1272w, https://substackcdn.com/image/fetch/$s_!Ns6h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ns6h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png" width="1100" height="214" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:214,&quot;width&quot;:1100,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55906,&quot;alt&quot;:&quot;The Open Group IT4IT lifecycle of digital products&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/197635849?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The Open Group IT4IT lifecycle of digital products" title="The Open Group IT4IT lifecycle of digital products" srcset="https://substackcdn.com/image/fetch/$s_!Ns6h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 424w, https://substackcdn.com/image/fetch/$s_!Ns6h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 848w, https://substackcdn.com/image/fetch/$s_!Ns6h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 1272w, https://substackcdn.com/image/fetch/$s_!Ns6h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ff20f5f-7268-48a7-9aa5-c7ee880dfcf4_1100x214.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">The Open Group <em>IT4IT lifecycle of digital products</em></figcaption></figure></div><p>The conversation around AI-driven software development has never been louder. From Amazon&#8217;s opinionated AI-Driven SDLC<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>  to the growing body of work around Spec-Driven Development<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> , the industry is moving quickly to position AI as the definitive solution to an age-old challenge: how do we build software faster, more reliably, and at greater scale?</p><p>These frameworks offer genuine value. The productivity gains for teams that adopt them are real, and the examples are compelling. However, the discourse consistently makes the same mistake: it scopes &#8220;the SDLC&#8221; to mean the build phase and little else.</p><p>The true software development lifecycle is far broader. It encompasses Ideation, Architecture, Planning, Build, Operations, Fixes, and Retirement, a complete arc from the first spark of a product idea to the deliberate decommissioning of a system. When we evaluate AI&#8217;s role through this wider lens, a more honest and more complicated picture emerges. AI is not a replacement for the SDLC process. It is, at its best, a powerful accelerator but only when its integration into the lifecycle is deliberately and carefully architected.</p><div><hr></div><h2>Why Small Teams Don&#8217;t Prove the Case</h2><p>It is worth acknowledging what AI-first development gets right. For solopreneurs, small startups, and lean product teams, an AI-first SDLC can be genuinely transformative. The context window of a modern AI system is sufficient to hold the full scope of a small codebase. One or two engineers can move with a speed that would have been impossible a few years ago. The gains are real.</p><p>The challenge is that these successes are being used to justify adoption at an entirely different scale, large enterprises with hundreds or thousands of engineers, hundreds of services, and decades of accumulated architectural decisions. The properties that make AI effective for a small team do not transfer cleanly to this environment.</p><p>At enterprise scale, the assumptions break down. A single AI agent cannot hold the full context of a distributed system spanning dozens of teams and hundreds of services. The clean feedback loop between a developer and an AI assistant becomes a tangled web of dependencies, competing priorities, and organizational constraints. Understanding why requires examining the most fundamental problem with AI at scale: non-determinism.</p><div><hr></div><h2>The Non-Determinism Problem</h2><p>Non-determinism is not a quirk of current AI systems that will eventually be engineered away. It is an inherent property of the probabilistic models that power them. For small-scale development tasks (writing a function, generating a test suite, summarizing documentation), this is largely acceptable. The cost of variation is low, and a human reviewer catches the drift.</p><p>At enterprise scale, the cost of non-determinism compounds rapidly.</p><p>Consider a large organization running hundreds of microservices across multiple teams. Each service represents a distinct bounded context, typically owned by a small team. Features and epics orchestrate work across these boundaries at a higher level. If an AI planning agent is responsible for generating specifications across multiple epics simultaneously, it must do so consistently (not just within a single session), but across repeated invocations, different teams, and changing business context.</p><p>This is where Spec-Driven Development begins to strain. Ask an AI agent to define the acceptance criteria for a given feature, and it will produce a reasonable answer. Ask it again tomorrow, with slightly different phrasing, and the answer will shift. At small scale, this is manageable. Across hundreds of services and dozens of teams, this drift accumulates into inconsistency that is difficult to detect and expensive to correct.</p><p>The deeper issue is accountability. Human developers navigate ambiguity through judgment, context, and professional accountability. When a decision leads to a poor outcome, there is a person who made that call and can learn from it. When an AI agent makes the same decision, a decision from a system that is non-deterministic by design, accountability becomes diffuse. Who owns the output? Who is responsible when acceptance criteria shift between sprints and the resulting system fails to meet business needs? These are not rhetorical questions. They are organizational challenges that must be answered before AI can be safely integrated at scale.</p><div><hr></div><h2>Architecture Consistency at Scale</h2><p>The non-determinism problem is most consequential when it touches architectural decisions. For large organizations, technical architecture is not a creative exercise, it is a discipline. Architecture principles, patterns, and guidance must be applied consistently across the landscape if that landscape is to remain manageable over time.</p><p>Consider what happens when architecture is delegated to an AI without constraints. Asked to design a new service, the AI might select a microservices approach. Asked again for a different service with similar requirements, it might favor a modular monolith. Asked a third time, it might propose an event-driven architecture. While each choice may be individually defensible, collectively they produce a fragmented landscape where every service is a unique artifact, each with its own operational patterns, its own failure modes, and its own runbooks.</p><p>This fragmentation also has direct operational and financial consequences. Operations teams cannot apply generalized expertise across services that each behave differently. Incident response becomes slower because runbooks cannot be standardized. Cloud costs become difficult to manage because cloud resource selections (Lambda versus EC2 versus ECS versus EKS), vary by service rather than following a consistent decision framework. FinOps programs, which depend on predictable patterns to optimize spend, are undermined by this inconsistency.</p><p>The solution is not to exclude AI from architectural decisions, but to constrain the space in which it operates. Guardrails, prescriptive pattern sets, and architectural governance frameworks give AI agents a bounded set of valid choices. Within that bounded space, AI can accelerate architectural work significantly. Outside it, the long-term costs outweigh the short-term gains.</p><div><hr></div><h2>Operations: The Hidden Cost of Upstream Decisions</h2><p>Operational complexity does not emerge at deployment time. It is designed in (or more accurately, it is neglected) at the planning and architecture phases. Every decision made upstream about how a service is structured, what data it produces, and how it communicates with its neighbors has a direct consequence for how it will operate in production.</p><p>This is the hidden cost that AI-SDLC frameworks consistently underestimate.</p><p>For AI agents to participate meaningfully in operations (like detecting anomalies, diagnosing failures, triggering remediations) they require rich, consistent observability signals. Logs must be structured and semantically meaningful. Metrics must cover the right indicators. Distributed traces must propagate correctly across service boundaries. These are not implementation details that can be added after the fact. They must be part of the initial planning phase; rather than discovered as gaps during the first production incident.</p><p>This introduces a critical architectural requirement: the feedback loop between operational agents and planning agents must be explicitly designed. When an operational agent encounters a failure it cannot diagnose because the necessary signals are missing, that information must flow back to the planning and architecture layers. The planning agent that generated the original specification must be capable of receiving and incorporating this feedback. Without this loop, the system learns nothing from production, and the same observability gaps are reproduced in every subsequent service.</p><p>Furthermore, operational agents cannot be generic. A service built on a Lambda-based event-driven pattern has fundamentally different failure modes than a service built on a long-running container. Effective operational AI requires specialization, agents that understand the specific patterns they are operating in, not agents that reason from first principles about every incident. This in turn, reinforces the argument for architectural consistency: a landscape with fewer distinct patterns requires fewer specialized agents and produces more predictable operational outcomes.</p><div><hr></div><h2>The Phases Nobody Talks About</h2><p>The build phase receives the majority of attention in AI-SDLC. This is understandable because it is where the most visible productivity gains occur, and it is the phase most responsive to automation. However, a lifecycle that begins at planning and ends at deployment is not a lifecycle ... it is a fragment.</p><p><strong>Ideation</strong> is where software begins. Before a line of code is written, before an architecture is selected, business context must be translated into product requirements. This is an activity that involves stakeholder negotiation, market understanding, strategic judgment, and organizational politics. AI can assist with this phase: synthesizing research, generating initial requirement drafts, identifying gaps in specifications. However, the judgment about what to build and why remains a human responsibility. AI-SDLC frameworks that begin at the planning phase are implicitly assuming that ideation has already been resolved, which is rarely true in practice.</p><p><strong>Fixes</strong> represent a continuous parallel track to feature development. Bug reports, production incidents, and security vulnerabilities do not pause while the planning agent generates the next sprint&#8217;s epics. AI agents that operate in the fixes track face a different set of constraints than those operating in the feature track: they must reason from incomplete information, work against time pressure, and frequently operate on legacy code that predates any AI involvement. Integrating fixes into an AI-SDLC requires explicit tooling for incident context ingestion, prioritization logic, and safe rollback mechanisms, none of which are addressed in current frameworks.</p><p><strong>Retirement and migration</strong> may be the most neglected phase of all. Every dependency within a service has a lifecycle of its own. Programming languages release new versions, and libraries reach end-of-life. When a core technology in a service&#8217;s stack loses community support or vendor maintenance, the cost of inaction compounds over time with security exposure, incompatibility with adjacent services, and eventual forced migrations under time pressure.</p><p>A complete AI-SDLC must account for this. It requires a dedicated monitoring capability with an agent or set of agents whose responsibility is tracking the dependency health of every service in the portfolio. When a dependency approaches end-of-life, the system should surface that signal to the planning layer before it becomes a crisis ... not after. This is not an unexpected requirement; rather, it is the operational reality of maintaining software at scale, and it is almost entirely absent from current AI-SDLC thinking.</p><div><hr></div><h2>What a Real Enterprise AI-SDLC Requires</h2><p>Having examined the gaps, it is possible to sketch out an AI-SDLC that actually works at enterprise scale. It is not a single agent, a single framework, or a single vendor&#8217;s platform. It is a system of systems and a set of specialized, constrained agents operating within a governance structure that preserves human accountability at the strategic layer.</p><p>The foundational principle is a clear division of responsibility. Human orchestrators own the &#8220;what&#8221; and the &#8220;why.&#8221; They define business strategy, set architectural principles, establish governance guardrails, and make the calls that carry accountability. AI agents own the &#8220;how&#8221;, by executing within the boundaries that human orchestrators define, accelerating the tedious and dependency-heavy work of implementation, and surfacing information that humans need to make better decisions.</p><p>This division only functions if the following components are in place:</p><p><strong>Guardrails and constrained pattern sets.</strong> Architectural AI agents must operate within a defined set of approved patterns. The set should be small enough to maintain consistency and large enough to cover legitimate variation. Deviations from approved patterns should require human approval, not AI discretion.</p><p><strong>Observability-first specifications.</strong> Planning agents must generate specifications that include explicit observability requirements, like what logs the service must produce, what metrics it must expose, what traces it must propagate. These requirements are not optional and must be validated before a service is considered complete.</p><p><strong>Explicit feedback loops.</strong> Operational agents must have a defined channel to communicate signal gaps and failure patterns back to planning and architecture agents. This loop closes the connection between what was designed and what is actually happening in production.</p><p><strong>Dependency monitoring.</strong> A dedicated agent or capability must track the health and lifecycle status of every dependency across the portfolio, surfacing EOL risks to the planning layer on a continuous basis.</p><p><strong>Human accountability checkpoints.</strong> Non-deterministic outputs in architectural decisions, acceptance criteria, and migration plans must pass through human review before they are committed to. AI generates the options; humans make the call.</p><p>Together, these components address the non-determinism problem not by eliminating it, but by containing it. AI operates freely within bounded, reversible, low-stakes decisions. Human judgment intervenes at the high-stakes, high-consequence points where accountability matters.</p><div><hr></div><h2>Conclusion: The Real Revolution</h2><p>The most important shift in enterprise software development is not the adoption of AI. It is the recognition that AI adoption requires architectural thinking of the same rigor and care as any other major system integration.</p><p>Organizations that treat AI-SDLC as a tool swap by replacing the old process steps with new AI-driven equivalents, will encounter the compounding costs described throughout this article: Fragmented architectures, Inconsistent observability, Untracked dependencies, and Accountability gaps that surface at the worst possible moments.</p><p>Organizations that succeed will be those that design the integration deliberately: defining the boundaries within which AI operates, building the feedback loops that keep the system honest, and preserving human judgment at the points where it matters most.</p><p>The question facing enterprise software leaders is not &#8220;how do we adopt AI in our SDLC?&#8221; It is a more precise and more demanding question: &#8220;how do we architect a system in which AI and human judgment each do what they do best, across the full lifecycle of every service we operate?&#8221;</p><p>That question does not have a simple answer. It requires the same systems thinking, strategic clarity, and organizational discipline that have always separated organizations that manage complexity well from those that are managed by it. AI does not change that requirement. Rather, it makes meeting that requirement more achievable than it has ever been.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>https://aws.amazon.com/blogs/devops/ai-driven-development-life-cycle/</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>https://www.thoughtworks.com/radar/techniques/spec-driven-development</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://ko-fi.com/perezcreations" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GrrQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!GrrQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!GrrQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!GrrQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GrrQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png" width="235" height="64.2428861788618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:984,&quot;resizeWidth&quot;:235,&quot;bytes&quot;:25538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://ko-fi.com/perezcreations&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://aaron824205.substack.com/i/197635849?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GrrQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 424w, https://substackcdn.com/image/fetch/$s_!GrrQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 848w, https://substackcdn.com/image/fetch/$s_!GrrQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 1272w, https://substackcdn.com/image/fetch/$s_!GrrQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F496d277c-c027-4ed6-bd46-d95a2ea99cd5_984x269.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Buy me a Coffee</figcaption></figure></div><p></p></div></div>]]></content:encoded></item></channel></rss>