<?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[Signal Over Noise]]></title><description><![CDATA[Most AI content is written by people selling something. This isn't. Signal Over Noise is a practitioner-first publication on AI agents and automation, written by a CTO who's made the expensive mistakes so you don't have to.]]></description><link>https://signalovernoise.tech</link><image><url>https://substackcdn.com/image/fetch/$s_!Owu3!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb7415cf-9ce5-438f-98c5-7acddf07ed8f_1280x1280.png</url><title>Signal Over Noise</title><link>https://signalovernoise.tech</link></image><generator>Substack</generator><lastBuildDate>Sat, 17 Oct 2026 04:28:06 GMT</lastBuildDate><atom:link href="https://signalovernoise.tech/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Justin Wilson]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[signalovernoisetech@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[signalovernoisetech@substack.com]]></itunes:email><itunes:name><![CDATA[Justin Wilson]]></itunes:name></itunes:owner><itunes:author><![CDATA[Justin Wilson]]></itunes:author><googleplay:owner><![CDATA[signalovernoisetech@substack.com]]></googleplay:owner><googleplay:email><![CDATA[signalovernoisetech@substack.com]]></googleplay:email><googleplay:author><![CDATA[Justin Wilson]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Fail Open, Fail Closed, or Ask: The Guardrail Choice]]></title><description><![CDATA[An unavailable judge should change the next state, not silently enlarge the grant.]]></description><link>https://signalovernoise.tech/p/fail-open-fail-closed-or-ask-the</link><guid isPermaLink="false">https://signalovernoise.tech/p/fail-open-fail-closed-or-ask-the</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Fri, 16 Oct 2026 11:03:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6bbi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>An unavailable judge should change the next state, not silently enlarge the grant.</em></p><div><hr></div><p>A guardrail outage should not grant an agent more authority than a working guardrail would. It should not necessarily stop every useful operation either. The failure contract belongs to the action: which dependency matters, what evidence remains available, and which effects are still permitted. One global fail-open switch cannot express those distinctions.</p><p>Consider a hypothetical support assistant handling a disputed subscription renewal. It can prepare a private response, propose a refund under an existing policy, or refer an exception to a supervisor. This is a proposed workflow, not a system I have deployed or measured. Its three operations share a conversation, but they should not share an outage response. Losing an optional writing check is different from losing the policy evidence required to move money.</p><p>The private draft can continue when a tone evaluator is unavailable, provided its existing grant still covers the work. In this design, the assistant uses an already approved local evidence snapshot and writes only to its isolated review workspace. It cannot fetch newly restricted customer records, send the response, or initiate a refund. Record the missing advisory check and retain draft status. Calling this fail-open is acceptable only if the opening is that narrow: one optional quality dependency has failed, while the actual authorization boundary remains intact.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6bbi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6bbi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 424w, https://substackcdn.com/image/fetch/$s_!6bbi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 848w, https://substackcdn.com/image/fetch/$s_!6bbi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 1272w, https://substackcdn.com/image/fetch/$s_!6bbi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6bbi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1805010,&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://signalovernoise.tech/i/220677190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.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_!6bbi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 424w, https://substackcdn.com/image/fetch/$s_!6bbi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 848w, https://substackcdn.com/image/fetch/$s_!6bbi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.png 1272w, https://substackcdn.com/image/fetch/$s_!6bbi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34be3f54-4b21-4c6c-aca0-543220927f67_1664x936.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Reversibility alone is not enough. Deleting a draft can undo a file write; it cannot undo disclosure to an unauthorized model endpoint. The degraded route therefore keeps the same approved processing destination, access restrictions, and storage boundary. If those controls cannot be established, drafting stops too. A fallback that sends the customer record to a new service has changed the operation, not merely recovered it.</p><p>The refund has a different resting state. Suppose the payment action requires a current policy decision and the policy service cannot answer. Retain the proposal without dispatching the payment. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html">OWASP&#8217;s authorization guidance</a></strong> recommends denial by default and permission validation on every request. Applied here, an unavailable decision supplies no affirmative permission. The assistant can explain the delay and preserve evidence without treating missing authorization as an inconvenience it should work around.</p><p>Separate a valid denial from a failed evaluation. An explicit false decision means the checked rule did not authorize this operation. A connection timeout means no usable response arrived. A missing decision may mean the application asked for a document that does not exist. <strong><a href="https://www.openpolicyagent.org/docs/rest-api">Open Policy Agent&#8217;s Data API</a></strong> can return HTTP 200 for an undefined document while omitting the result property. Successful transport is not an allow decision. The adapter must validate the expected result shape and value rather than interpreting an empty response as permission.</p><p>Those states may all prevent payment, but they require different recovery. A denial needs a permitted change or a legitimate exception process. An unavailable engine needs service recovery. An undefined decision needs investigation of the queried path, loaded policy, and required inputs. Preserve those reasons separately. Otherwise, operators cannot distinguish a customer who is ineligible from a broken integration that is holding every eligible customer.</p><p>The exception belongs in a human queue only if a supervisor actually has authority to decide it. Present the resolved customer account, disputed charge, proposed amount, policy limitation, supporting records, and an explicit expiry. The default when nobody answers is no refund, not consent. If the queue service itself is unavailable, retain an undelivered escalation with an owner; do not describe it as awaiting a reviewer who never received it. A private draft can remain available while the consequential operation waits.</p><p>An approval that arrives later must still match the pending decision. The customer might have received a refund through another channel, the proposed amount might have changed, or the supervisor&#8217;s authority might have been revoked. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Transaction_Authorization_Cheat_Sheet.html">OWASP&#8217;s transaction-authorization guidance</a></strong> calls for acknowledgement of significant transaction data and a final control before execution. In this design, changed significant data or an expired approval returns the item to review. Clearing the queue must not mean executing yesterday&#8217;s decisions against today&#8217;s accounts.</p><p>A temporary dependency failure also does not justify indefinite recovery attempts. <strong><a href="https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/">Amazon&#8217;s retry guidance</a></strong> explains how retries can amplify load and why backoff and jitter matter. A read-only policy lookup needs a bounded attempt budget within the operation&#8217;s deadline, with retry ownership in one layer. Exhaustion leaves the payment held with a reason and next owner. A larger model is not a replacement policy service, and repeated requests do not make absent evidence more authoritative.</p><p>The most consequential timeout occurs after the payment request leaves the application. That is no longer a missing authorization decision. The provider may have accepted the refund before its response disappeared. Amazon&#8217;s guidance explicitly warns that a timeout does not establish the absence of side effects. Mark the outcome unknown, retain the original operation identity, and reconcile provider state through a permitted read. Use the provider&#8217;s documented idempotency behavior where available; otherwise, do not automatically repeat the monetary action to see whether it works.</p><p>Recovery needs an admission rule, not just a green health indicator. Before releasing an undispatched held refund, obtain a usable current policy result, check the exact charge and proposed effect, reconcile any existing attempt, and establish any required live approval. Confirm that the execution and audit dependencies are also available. Restore work gradually within the defined capacity instead of releasing an entire backlog because one probe succeeded. This is a proposed operating rule, not a performance claim about a particular payment platform.</p><p>An emergency exception must be narrower than disabling the gate. If the organization permits one, name the authorized owner, eligible operations, evidence required, expiry, and independently retained record. A temporary route for a supervisor-approved refund should not also enable arbitrary credits, external messages, or new recipients. Keep the original unavailable dependency visible. The override records who accepted a defined risk; it does not rewrite the outage as an ordinary successful check.</p><p>The useful decision matrix can therefore stay small. Optional tone evaluation unavailable: continue the already authorized private draft, flag the missing check, and prevent sending. Required payment policy unavailable or undefined: retain the proposal without a payment attempt. Legitimate policy exception: request a scoped supervisor decision that expires without execution. Payment response lost after dispatch: reconcile the original outcome before considering another effect. These are proposed dispositions for this workflow, not universal defaults for every application that uses an agent.</p><p>Exercise those transitions before depending on them. In controlled tests, remove the optional evaluator, return an undefined policy result with HTTP 200, let a review expire, change the charge after approval, and lose a provider response after acceptance. Inspect actual downstream effects and durable records. Check that private drafting remains useful without allowing a payment, that a late approval cannot resurrect an expired operation, and that an unknown refund is not automatically sent twice. These are suggested tests, not results reproduced here.</p><p>An outage is when a permission design stops being theoretical. The assistant should retain useful work, leave forbidden effects untouched, and expose the exact evidence needed to proceed. Give each operation a resting state that the executor can enforce when the judge, the network, or the reviewer is absent. Recovery should restore the missing evidence, not reward the failure with a larger grant.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Tool Authorization Envelope]]></title><description><![CDATA[Bind permission to the operation that actually runs, not the explanation that requested it.]]></description><link>https://signalovernoise.tech/p/the-tool-authorization-envelope</link><guid isPermaLink="false">https://signalovernoise.tech/p/the-tool-authorization-envelope</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Thu, 15 Oct 2026 08:55:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!yb17!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Bind permission to the operation that actually runs, not the explanation that requested it.</em></p><div><hr></div><p>A tool call should arrive at execution with less authority than the model imagined, not more. A request to prepare a release can reasonably produce a proposed upload. It cannot manufacture permission to publish. The useful boundary is an authorization envelope: an application-controlled record of exactly which action may run, against which resource, under which grant, and until when.</p><p>Consider a hypothetical assistant preparing a release of an internal software package. It may inspect approved source, build an artifact, and run checks. Publishing to the internal registry requires a release manager&#8217;s confirmation; publishing to a public registry is prohibited under this grant. This is a proposed reference architecture, not a deployment or benchmark I have measured. Its central job is to keep the release decision attached to the artifact that actually reaches the registry.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yb17!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yb17!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!yb17!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!yb17!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!yb17!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yb17!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2527557,&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://signalovernoise.tech/i/220498204?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.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_!yb17!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!yb17!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!yb17!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!yb17!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F897e22a1-3407-4869-ae92-47a638c1445e_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 assistant does not receive the publishing credential. It proposes a structured operation to a broker that owns the execution boundary. That proposal names the tool, artifact reference, registry, package, version, and requested effect. The broker adds authenticated caller identity, delegated scope, environment, current policy revision, and a request identifier from trusted state. An argument supplied by the model cannot overwrite those fields.</p><p>Parse before judging. Reject unknown operations and malformed arguments, resolve the registry and artifact through approved identifiers, and compute the artifact digest from stored bytes. Do not let an apparently harmless wrapper conceal an unrestricted shell command. If an operation invokes scripts or follows redirects, the adapter must constrain those effects too. The envelope describes a resolved action, not merely the string that made the action look acceptable.</p><p>Deterministic policy then narrows the possible outcomes. The public registry is denied regardless of a model&#8217;s assessment. A read-only metadata lookup can proceed under an explicit matching grant. The internal upload remains eligible but held for confirmation. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html">OWASP&#8217;s authorization guidance</a></strong> recommends least privilege, denial by default, and permission validation on every request. The practical consequence is that a convincing explanation cannot add an operation to the caller&#8217;s scope.</p><p>An existing policy engine can evaluate those structured rules; a second model is not required to compare a registry identifier with an allowed set. <strong><a href="https://www.openpolicyagent.org/docs">Open Policy Agent</a></strong> explicitly separates policy decisions from enforcement. The broker still has to consume the decision and withhold the credentialed call when it does not pass. Installing a policy engine beside an unrestricted execution route would preserve the route that matters most.</p><p>Reserve the bounded decision model for a question the rules cannot settle cheaply. It might assess whether the proposed release notes imply an external disclosure inconsistent with the task. Supply the necessary approved evidence and a fixed set of outcomes, including insufficient evidence. Record model identity, evidence references, decision, and applicable evaluation policy. Its output may raise an eligible operation to review or support a permitted low-impact path; it cannot lower a deterministic denial or waive required confirmation.</p><p>That gray-zone decision needs an operating threshold established on representative labeled cases, with false allows distinguished from needless holds. No universal probability cutoff follows from the architecture. An unfamiliar operation, missing evidence, or a result outside the accepted schema should retain the hold. A model that returns a valid score has answered a typed question; the application still owns what that answer permits.</p><p>The release manager should see the internal registry, package version, artifact digest, relevant check results, and the fact that this will create a published release. Approval comes through an authenticated channel and binds to that resolved operation, not to the assistant&#8217;s summary. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Transaction_Authorization_Cheat_Sheet.html">OWASP&#8217;s transaction-authorization guidance</a></strong> calls for acknowledgement of significant transaction data, server-side enforcement, limited validity, and a final check before execution. A later rebuild changes the digest and invalidates this approval.</p><p>The broker can now issue a short-lived, single-use authorization record. Bind it to caller, action, resource, artifact digest, policy revision, approval reference, expiry, and an unpredictable operation identifier. Store it server-side or protect its integrity with a mechanism the actor cannot forge. A digest alone only identifies bytes; it does not authenticate permission. Immediately before dispatch, recheck current scope, revocation, artifact identity, and the record&#8217;s unused state, then claim it atomically so competing workers cannot both release the operation.</p><p>Execution uses the least-privileged credential available for that registry and package. The downstream service should enforce those limits as well; the broker must not be the only thing separating a narrow task from an account-wide administrator token. Keep alternate clients, network destinations, and direct credential access outside the assistant&#8217;s reach. This architecture loses its authorization boundary if the agent can perform the same upload through a different tool.</p><p>Prompt injection belongs in that threat model. Release notes, repository comments, and retrieved pages can contain instructions claiming that approval already exists. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html">OWASP&#8217;s prompt-injection guidance</a></strong> identifies indirect instructions and agent-connected tools as attack surfaces. Preserve that material as untrusted evidence, separate from application-owned policy and approval records. A second model reading the forged instruction does not make it authoritative. Even a fully deceived judge must remain unable to mint the release manager&#8217;s approval.</p><p>Define failure behavior for each stage rather than assigning the whole system one fail-open switch. If a required policy lookup, semantic gate, or confirmation service times out, this publishing operation stays unexecuted with an owner and expiry. An optional prose-quality check could be unavailable without blocking an otherwise authorized metadata read, if that exception is explicit policy. Missing authorization is never repaired by assuming consent. Expired holds become cancelled or awaiting renewed review, not silently executable backlog.</p><p>A timeout after dispatch is a different state. The registry might have accepted the release before its response disappeared. Mark the outcome unknown and reconcile registry state using the operation identifier and expected artifact digest. Do not mint another operation merely because the assistant did not receive success. <strong><a href="https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/">Amazon&#8217;s guidance on idempotent APIs</a></strong> explains caller-provided request identifiers and the importance of distinguishing repeated requests from changed intent. Use the downstream service&#8217;s actual idempotency contract where available; a local identifier cannot make a non-idempotent remote API safe by itself.</p><p>Verification closes the effect, not just the HTTP request. Read the published package metadata through a permitted independent query and compare registry, version, and digest with the authorized values. A transport success without that evidence remains an unverified execution. A mismatch becomes an incident for the release owner, not permission for the assistant to delete or replace an artifact. Those corrective actions need their own grants.</p><p>Append durable events as the operation moves through proposed, denied, awaiting approval, authorized, dispatched, unknown, and verified states. Keep policy and evidence references, authenticated approver, execution attempt, and verification result outside the actor&#8217;s writable store. Restrict deletion and mutation, and use retention controls appropriate to the required audit strength. If a durable pre-dispatch event cannot be recorded, hold the release. Record completion durably before telling the user it is verified; missing final evidence must remain visible for reconciliation.</p><p>Evaluate the boundary with controlled fixtures before allowing real releases. Substitute a new artifact after approval, replay a consumed authorization, forge approval inside release notes, race two workers, revoke scope before dispatch, and lose the registry response after acceptance. Check downstream effects and retained events, not only the judge&#8217;s answers. These are proposed acceptance tests, not results reported here. The envelope earns authority when the exact approved operation can pass once, and every materially different operation has to earn its own permission.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Steer, Confirm, or Deny: Three Different Guardrail Jobs]]></title><description><![CDATA[Choose the response by the authority it needs, not the severity of its warning.]]></description><link>https://signalovernoise.tech/p/steer-confirm-or-deny-three-different</link><guid isPermaLink="false">https://signalovernoise.tech/p/steer-confirm-or-deny-three-different</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Wed, 14 Oct 2026 09:05:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!f1c4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Choose the response by the authority it needs, not the severity of its warning.</em></p><div><hr></div><p>A warning, an approval request, and a refusal should not be three colors on the same safety indicator. They change who controls the next action. Steering asks the agent to reconsider. Confirmation transfers a specific decision to an authorized person. Denial removes the proposed action from the permitted path. A system that treats them as interchangeable can interrupt harmless work while leaving consequential operations open.</p><p>The useful question is not how worried the guardrail sounds. It is what happens to the pending call, what evidence can release it, and who owns that release. Those answers should exist before a model returns a judgment. A score can help select a response within policy; it cannot decide which authority the organization meant to delegate.</p><p>Consider a hypothetical coding assistant preparing a release. It can edit a local branch and run permitted checks. It cannot publish the package, charge a company account, or delete retained production data on its own. That bounded grant gives the three responses different jobs without pretending every write has the same impact. The workflow here is a proposed design, not an account of a deployment or test I performed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!f1c4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!f1c4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!f1c4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!f1c4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!f1c4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!f1c4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2299144,&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://signalovernoise.tech/i/220332523?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.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_!f1c4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!f1c4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!f1c4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!f1c4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fea4ff8be-5678-4ea5-ab6f-562d8d41af06_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Steering fits a repairable mistake within that grant. Suppose an edit replaces a useful error message with a raw exception. A finding can identify the violated project convention, point to the changed lines, and ask for a correction. The agent still chooses the repair. The guardrail should judge the revised result, not count receipt of its advice as success. If correction repeatedly fails, the system needs a bounded stop or review path rather than an endless exchange of increasingly emphatic warnings.</p><p>Reversibility requires an operating boundary, not merely a version-control command. An edit can be reverted while a credential exposed by the edit remains compromised. A local check may invoke a script with network effects. I would reserve autonomous repair for work whose affected resources, downstream effects, and recovery path are actually bounded. Uncertain impact is a reason to hold the proposed operation and obtain evidence, not to label it reversible because its filename looks ordinary.</p><p>Steering also does not imply that the original call runs. <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/src/extension.ts">Pi-Warden&#8217;s tagged 1.7.0 implementation</a></strong> illustrates the distinction: its steer response to a held action returns a blocking result and tells the agent to re-plan or ask. Its advise mode lets the corresponding hold-level finding become a warning, while confirm mode uses a person-facing dialog. These are source-reviewed behaviors, not runtime results reproduced here. The product&#8217;s mode name matters less than whether its host releases the call.</p><p>A temporary hold for repair differs from a hard denial. With steering, an eligible alternative can proceed after fresh checks: change the implementation, narrow the target, or choose a non-destructive inspection. With denial, the forbidden operation remains forbidden even if the agent supplies a more persuasive rationale. The distinction should survive paraphrasing and alternative tool routes. Otherwise, the agent learns to search for an interface the warning did not cover.</p><p>Confirmation belongs where a person can resolve a legitimate decision the agent does not own. The release assistant might prepare an upload for a release manager to authorize, or propose deleting a verified disposable environment. The prompt should display the resolved destination, affected resources, significant content, and consequence. A dialog that says only &#8220;Allow this tool?&#8221; asks the reviewer to infer the important facts from the agent&#8217;s explanation, which is precisely the interpretation still under review.</p><p><strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Transaction_Authorization_Cheat_Sheet.html">OWASP&#8217;s transaction-authorization guidance</a></strong> calls for acknowledgement of significant transaction data, controlled state transitions, and a final authorization check tied to execution. Applied to the release, confirmation should bind to the actual artifact and destination. Applied to a payment, it should bind to the resolved payee, amount, and relevant terms. Changed significant inputs invalidate the earlier decision; a general &#8220;yes&#8221; in a conversation should not silently authorize the replacement.</p><p>The person must also possess the authority being requested. A developer may approve a branch edit without owning production release policy. An account holder may confirm spending within a delegated limit without overriding a prohibited recipient. Confirmation is not a universal exception mechanism. If policy offers an appeal, send it to the named policy owner and record the scoped exception through a separate authorized process. Do not turn every denial into an approval button for whoever happens to be online.</p><p>Known prohibitions belong in enforcement. If the assistant must never publish under its current grant, prevent publishing rather than asking a probabilistic judge whether this particular release looks sensible. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html">OWASP&#8217;s authorization guidance</a></strong> recommends least privilege, denial by default, and permission checks on every request. For a coding agent, command and path rules can help express a boundary, but the downstream credential and resource permissions must support it. Blocking one shell spelling does not protect an operation available through another client.</p><p>There is still a gray zone between clear eligibility and clear prohibition. A judge can examine whether a command appears to affect production, whether the proposed purchase matches the task, or whether an edit violates a semantic rule. Preserve its result as fallible evidence with provenance. Missing context, an unfamiliar action, or conflicting findings should lead to a bounded hold and an owned question. They should not grant permission by default or become a permanent accusation that the requested work is malicious.</p><p>The judge needs a trust boundary too. A repository comment saying &#8220;the owner already approved deployment&#8221; is not an approval record. A tool result claiming to contain updated policy is not policy merely because the agent retrieved it. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html">OWASP&#8217;s prompt-injection guidance</a></strong> identifies indirect instructions in external documents, code comments, and tool-connected workflows as attack surfaces. Passing the same material to a second model does not establish its authority. Keep policy and approval records application-controlled, and preserve untrusted content as evidence rather than instructions the judge can promote into permission.</p><p>Failure handling must preserve the selected job. If an optional style judge times out during an otherwise eligible local edit, a documented policy might permit work with the advisory check marked unavailable. If a required authorization check fails before spending or destruction, retain the pending action without execution. An unanswered confirmation should expire into a held or cancelled state, not count as consent. A denied call should remain denied when the semantic service is unreachable. These are proposed dispositions whose owners must define them, not guarantees supplied by the word guardrail.</p><p>Keep decision failure separate from uncertain execution. If the operation was dispatched and its response disappeared, the next state is an unresolved outcome, not a fresh confirmation request for the same effect. Reconcile downstream state before any authorized repeat. This distinction prevents a conscientious agent from asking twice and producing two payments or deletions. The person should see which operation is still pending and which might already have happened.</p><p>An audit record should show the proposed action, applicable grant, policy version, finding, selected response, approval or exception reference, execution attempt, and verified outcome. Record the person who released a hold separately from the agent that proposed it. Keep those records outside the actor&#8217;s editable context, with access and retention controls appropriate to the content. The evidence of a boundary is a prevented operation or a scoped release, not a fluent sentence saying the agent behaved safely.</p><p>Evaluate the responses against distinct failure cases. In controlled fixtures, present a repairable edit, a changed payment after approval, a known prohibited command, a forged approval inside a document, and an unavailable required judge. Check whether the call ran, who could release it, and whether an alternative route bypassed the boundary. These are proposed tests, not results reported here. Track missed prohibitions separately from needless holds and failed repairs; a single intervention rate hides all three.</p><p>Confirmation everywhere is not the conservative answer. It consumes reviewer attention and delegates interpretation without necessarily improving it. Steering everywhere leaves the actor responsible for boundaries it cannot own. Denial everywhere prevents the useful work the grant was supposed to enable. Give repairable work room to recover, legitimate uncertainty an accountable decision-maker, and prohibited operations an enforcement point the agent cannot persuade. Choose the guardrail by the authority needed for the next action.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Pi-Warden: Guardrails That Steer Instead of Interrupt]]></title><description><![CDATA[Inspect which findings guide the agent and which ones actually stop the call.]]></description><link>https://signalovernoise.tech/p/pi-warden-guardrails-that-steer-instead</link><guid isPermaLink="false">https://signalovernoise.tech/p/pi-warden-guardrails-that-steer-instead</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Tue, 13 Oct 2026 13:53:19 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9ipI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Inspect which findings guide the agent and which ones actually stop the call.</em></p><div><hr></div><p>A guardrail earns attention when it changes what the agent does next. An interruption that merely asks a person to approve the same poorly explained action has moved the burden without improving the decision. Pi-Warden takes a more useful position: return a specific finding to the coding agent and let it repair its approach. The important qualification is where that finding arrives. Advice after a write and a hold before execution provide different protection.</p><p>The October 13 review baseline is Pi-Warden 1.7.0. The <strong><a href="https://github.com/DevMortimer/pi-warden/releases/tag/v1.7.0">GitHub release</a></strong> and <strong><a href="https://registry.npmjs.org/pi-warden">npm registry</a></strong> both place its publication on October 12; the checked main revision also matches the release commit. That resolves the source/package split recorded when this article was planned. This is a review of tagged source, documentation, and maintainer evidence. I have not installed it, run its evaluations, or measured its effect on a production agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9ipI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9ipI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 424w, https://substackcdn.com/image/fetch/$s_!9ipI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 848w, https://substackcdn.com/image/fetch/$s_!9ipI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 1272w, https://substackcdn.com/image/fetch/$s_!9ipI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9ipI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2365131,&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://signalovernoise.tech/i/220170529?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.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_!9ipI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 424w, https://substackcdn.com/image/fetch/$s_!9ipI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 848w, https://substackcdn.com/image/fetch/$s_!9ipI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.png 1272w, https://substackcdn.com/image/fetch/$s_!9ipI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F534468a1-15de-4551-98f6-7f785c264c6d_1672x940.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 integration boundary is specific. Its <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/package.json">package manifest</a></strong> requires Node.js 22.19.0 or later, depends on pi-typesafe, and declares optional Pi coding-agent and terminal-UI peers from 0.85.1 to below 1.0. The documented installation route is Pi&#8217;s package installer, followed by enabling judgments and initializing project rules. Offline checks can operate without a TypeSafe key; remote judgments require consent. There is no declared GPU requirement in that manifest. This is an extension around a host agent, not a local model bundle with a hardware benchmark.</p><p>Compatibility should not expand by association. The <strong><a href="https://github.com/DevMortimer/pi-warden/issues/127">cross-host integration issue</a></strong> still tracks work for Claude Code, Codex, and OpenCode; its proposed adapters are not a released compatibility guarantee. The <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/docs/guards.md">guard documentation</a></strong> also describes platform-specific scratch-deletion behavior: its birth-time-based session exemption differs on Linux from macOS and Windows. Verify the intended host, operating system, and acting model together. This review establishes no tested compatibility matrix or universal model-quality claim.</p><p>Its useful everyday loop starts with a rule the project can explain. Suppose an API handler must return a meaningful user-facing error rather than expose a raw exception. A proposed edit may satisfy the compiler while violating that convention. The <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/src/rules.ts">rules implementation</a></strong> builds bounded questions from the applicable rule text and changed content, then supplies findings for correction. That is a plausible job for semantic judgment. A deterministic linter should still own the checks it can express reliably.</p><p>Coverage needs inspection before trust. The still-open <strong><a href="https://github.com/DevMortimer/pi-warden/issues/63">rule-cap issue</a></strong> describes rules falling beyond a 31-question limit. The tagged implementation has progressed beyond that issue&#8217;s original description: it scopes edit rules to the target path before applying the cap. More than 31 applicable edit rules can still leave some unjudged. A long policy file is therefore not evidence that every instruction reached the judge. Check the effective rule set and dropped counts with a representative file from each important area.</p><p>The action guard operates at an earlier boundary. In the <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/src/extension.ts">Pi extension&#8217;s tool-call handler</a></strong>, a held action in the default steer mode returns a blocking result before the tool runs. The agent receives the reason and can choose a recoverable alternative or explain why it needs approval. Confirm mode uses a user dialog when available; advise mode lets model-generated holds become warnings. Explicit deny rules still block. Describing the whole product as merely advisory would miss this actual execution hook.</p><p>A hold does not make every judgment a hard policy rule. The consequential default is in the <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/src/config.ts">tagged configuration</a></strong>: the built-in action floor uses evidence mode. Pattern matches become evidence for the judge, rather than independently setting the hold level when a judge answers. Level mode keeps those patterns as a minimum that judgment can raise. User-declared command and path policies are separate controls. If a prohibition must survive a confident model answer, encode and test it as an explicit enforced rule.</p><p>Take a hypothetical release workflow. An agent asked to prepare a package might propose publishing it. A semantic judge can consider the request and distinguish preparation from release, but the organization may prohibit this agent from publishing under any circumstances. That requirement belongs in a deny rule and a credential boundary the agent cannot circumvent. Keeping the deployment credential unavailable is stronger than hoping every spelling of a publishing command is recognized. Pi-Warden&#8217;s in-process hook can improve the host&#8217;s behavior without becoming an operating-system sandbox.</p><p>Failure behavior reinforces that distinction. The <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/src/guard.ts">action evaluator</a></strong> restores built-in pattern levels when a judgment request fails in evidence mode. A destructive pattern can therefore remain held during an outage. The default fail-open setting does not impose a blanket hold on every other uncertain call; setting it false raises failed judgments to a hold. The default request timeout is five seconds. Test the exact action with the judge unavailable, rather than assuming either universal denial or universal permission from the setting&#8217;s name.</p><p>Approval has its own interpretation step. The <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/src/action-guard.ts">action-guard state machine</a></strong> tracks a previous hold and a new user reply. It asks about approval for a held call under that reply, consumes an approval once, and discards a cached sibling judgment if the input changed. It does not require the retry to match the earlier command byte for byte. Offline approval uses a heuristic. That can support conversational convenience, but I would not equate it with approval cryptographically bound to a reviewed deployment artifact.</p><p>The rest of the product addresses expensive habits rather than authorization alone. The <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/README.md">tagged overview</a></strong> describes checks for repeated failing approaches, unverified completion, unsupported causal claims, and low-value generated code. These findings can send an agent back to inspect evidence instead of declaring victory. Their value depends on what follows: a relevant passing check, a corrected change, or an honest unresolved result. A nudge followed by another tool call is useful behavioral evidence, but it cannot by itself certify that the task is complete.</p><p>The maintainer&#8217;s <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/eval/reports/2026-10-01-field-usage/README.md">September 16 through October 1 field report</a></strong> provides a concrete example. After 124 completion-check nudges, 94 were followed by a verification command within the next four agent messages. The report explicitly says this does not establish that the nudge caused the check. It covers one maintainer, one machine, and changing versions predating 1.0. Its hold records also lack outcomes for 308 of 419 holds. Those limits belong beside the attractive result.</p><p>The project&#8217;s paired-run and replay reports remain author-run evidence too. A replay can compare thresholds against recorded calls without proving how an agent would adapt after different interventions. A paired agent run can observe behavior, but its result still depends on the tasks, acting model, rule set, and acceptance rubric. I would reproduce a small comparison on permitted work before adopting a threshold: keep deterministic checks identical, record missed violations and needless interruptions separately, and include the cost of repair. Reduced prompting is an advantage only when consequential mistakes do not disappear with it.</p><p>Remote context is another adoption decision. The <strong><a href="https://github.com/DevMortimer/pi-warden/blob/v1.7.0/docs/data-handling.md">data-handling contract</a></strong> enumerates guard-specific payloads, including prompt context, command or path information, changed-code samples, rules, and completion evidence. Redaction is explicitly best effort. Opt-in context filtering can send an entire large output in redacted chunks, while saved full outputs remain local and may contain secrets. Review both destinations and retention before enabling features on private repositories. A smaller judge request is still a disclosure.</p><p>Version 1.7.0 adds a narrowly configured exception for share-link query parameters that would otherwise be masked in tool results. That release detail illustrates the maintenance burden: overly broad masking can break useful evidence, while overly broad exceptions can disclose credentials. The setting is empty by default and user-controlled. An operator should review the actual payload and output behavior for permitted examples, not treat either redaction or a readable link as proof of safe handling.</p><p>I would trial Pi-Warden on a bounded Pi workflow where rule repair and verification discipline are recurring problems. Keep the host and package pinned, give the agent limited credentials, and exercise a prohibited command, an unavailable judge, excess applicable rules, and an ambiguous approval reply. Record whether the call ran and whether the work improved. Let steering earn more autonomy through observed correction; keep every irreversible boundary backed by a component that can still say no.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Permission Is a Decision, Not a Prompt]]></title><description><![CDATA[The authority that releases an action must survive the model being wrong.]]></description><link>https://signalovernoise.tech/p/permission-is-a-decision-not-a-prompt</link><guid isPermaLink="false">https://signalovernoise.tech/p/permission-is-a-decision-not-a-prompt</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Mon, 12 Oct 2026 09:49:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_yGC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The authority that releases an action must survive the model being wrong.</em></p><div><hr></div><p>An agent that asks itself whether an action is safe still owns both sides of the decision. It proposes the operation, interprets the evidence, and decides whether its interpretation is sufficient. Adding a paragraph about caution can improve its behavior. It cannot create a boundary that survives the agent being wrong. Permission becomes meaningful when another component can prevent execution even after the model has decided to proceed.</p><p>Last week&#8217;s routing problem was choosing which capability should handle a request. This week&#8217;s problem starts when the chosen capability can change something. A useful answer and an authorized action require different evidence. The distinction matters even for a mundane workflow: an assistant preparing a customer incident update from internal records. Drafting the explanation, selecting attachments, and sending the message should not inherit one undifferentiated grant to &#8220;handle the incident.&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_yGC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_yGC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!_yGC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!_yGC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!_yGC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_yGC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2133661,&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://signalovernoise.tech/i/219994334?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.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_!_yGC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!_yGC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!_yGC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!_yGC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7159b38b-5bbc-4183-ab3a-0be115d5eb9d_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Consider that assistant as a proposed design, not a deployment I have tested. The user asks for a draft addressed to an existing customer contact. An incident note contains a suggested distribution list and says that the full diagnostic bundle should accompany the update. The model may reasonably consider those details relevant. Neither detail establishes that the suggested recipients may receive the bundle or that the user authorized sending anything. Retrieved content can supply facts without becoming a source of permission.</p><p>Four responsibilities need distinct owners. Model advice interprets what the user wants and proposes an action. Application policy defines which actions are eligible under the organization&#8217;s rules. User consent grants the requested action within the user&#8217;s own authority. Enforcement checks those inputs and controls the credential or operation that changes the system. Combining their descriptions in one prompt does not combine their authority. A polished explanation from the model is still advice.</p><p>This is established authorization engineering applied to a new caller. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html">OWASP&#8217;s authorization guidance</a></strong> recommends denying by default, checking permissions on every request, and enforcing access controls where the caller cannot bypass them. A logged-in identity alone does not establish access to every object. For the incident assistant, the relevant question includes the specific customer, document, destination, and operation. &#8220;The agent is trusted&#8221; leaves those decisions unanswered.</p><p>The boundary therefore needs explicit inputs that the application can verify. In this example, I would carry the authenticated requester, resolved recipient identifiers, exact attachment revisions, requested operation, applicable policy version, and evidence of any required approval. The model can propose a recipient name; trusted application code resolves the actual account and its relationship to the customer. A model-generated field saying &#8220;approved&#8221; has no authority unless it points to an approval the application can independently establish.</p><p>Separate authority does not necessarily require another model, machine, or service. It requires an enforcement path the acting model cannot rewrite or avoid. <strong><a href="https://www.openpolicyagent.org/docs">Open Policy Agent documents the separation between policy decisions and enforcement</a></strong>: the application supplies structured input, obtains a policy result, and must enforce it. The important integration question is where a denied result stops dispatch. Calling a policy engine and then letting the agent decide whether to respect its answer preserves the original problem.</p><p>Deterministic rules should establish the floor before uncertain interpretation begins. In the proposed incident workflow, a draft-only grant cannot authorize sending. An attachment classified for internal use cannot become externally shareable because a model finds it helpful. A missing recipient identity should prevent delivery rather than trigger a guess. These are proposed rules for this example, not universal rules for every organization. Their owner must define them, and the execution path must apply them consistently.</p><p>A decision model can still help with the gray zone. It might identify whether a proposed explanation appears to reveal operational detail that needs review, or whether the requested action diverges from the stated task. Its output is evidence for a policy-controlled transition. An unavailable judge, an ambiguous result, or missing context needs an explicit disposition: retain the draft and route the unresolved question to an authorized reviewer. Calling a larger model does not supply the absent authority.</p><p>Consent deserves more precision than a button labeled &#8220;Continue.&#8221; If the user eventually requests delivery, show the resolved recipients, the message, and the exact attachments that will leave the system. <strong><a href="https://cheatsheetseries.owasp.org/cheatsheets/Transaction_Authorization_Cheat_Sheet.html">OWASP&#8217;s transaction-authorization guidance</a></strong> calls for acknowledgement of significant transaction data and a final authorization check tied to execution. Applied here, approval should bind to the reviewed package. A changed recipient or attachment requires a new decision rather than reuse of the old confirmation.</p><p>That does not mean asking permission for every keystroke. The application can honor a prior grant for a bounded class of work while checking that each operation remains inside it. Preparing the draft and running an authorized read-only check need not repeatedly interrupt the user. The confirmation should resolve a real boundary, such as sending the reviewed material outside the organization. Repeated vague prompts add friction without clarifying what the person actually authorized.</p><p>The credential boundary determines whether those distinctions survive contact with the tools. A draft assistant with an unrestricted mail credential can bypass a carefully designed send tool through another available interface. <strong><a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/">OWASP&#8217;s excessive-agency guidance</a></strong> recommends minimal tool functionality, minimal downstream permissions, and authorization outside the model. For this design, keep sending behind the service that checks the grant. Inventory alternate routes as part of the boundary, including shell access and general network clients where they exist.</p><p>The permission check also has a lifetime. A reviewer can approve one attachment revision while another process replaces it before dispatch. The execution service should bind the decision to the reviewed bytes or immutable revision and reject a changed package. Approval should expire under a documented policy, and revocation must remain effective before execution. These controls cost more than carrying a Boolean through a chat session, but that Boolean cannot explain what was approved after the underlying work changes.</p><p>Authorization and successful execution need separate records. A permitted send can fail, and a timeout can leave its outcome unknown. Preserve the operation identifier and reconcile the downstream state before repeating a potentially completed effect. The application should report &#8220;delivery unresolved&#8221; when that is the evidence, rather than allowing the model to turn a missing response into either success or a fresh grant. A retry is another execution decision, not an excuse to forget the first one.</p><p>Keep the audit record outside the actor&#8217;s editable conversation. Record the request, resolved resource references, policy version, decision, approval reference, execution attempt, and verified outcome under a shared operation identifier. <strong><a href="https://www.openpolicyagent.org/docs/management-decision-logs">Open Policy Agent&#8217;s decision-log documentation</a></strong> shows how policy-query events can carry inputs and policy metadata, and describes masking sensitive fields. That is useful decision evidence; the application still needs execution evidence and storage controls. Copying a transcript into a mutable file does not make it an immutable audit trail.</p><p>The distinction is testable without trusting a model&#8217;s explanation. In a controlled test, give the assistant a prohibited send request and check whether the service prevents it. Change an attachment after approval, remove required policy input, make the judge unavailable, and present a note that claims the user already consented. These are proposed tests, not results from this article. Check the denied or held operation and its record, not merely whether the assistant apologizes.</p><p>A system can pass ordinary tasks while failing every meaningful boundary test. Judge its permission design by the action it refuses even when the model confidently recommends it, the ambiguity it hands to a named owner, and the record that survives a failed attempt. Grant autonomy to a defined operation with defined evidence. The component that wants to act should have to satisfy the boundary, not narrate its way through it.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[A Four-Tier Model Router You Can Explain]]></title><description><![CDATA[Every destination needs an eligibility rule, an acceptance test, and an owned way out.]]></description><link>https://signalovernoise.tech/p/a-four-tier-model-router-you-can</link><guid isPermaLink="false">https://signalovernoise.tech/p/a-four-tier-model-router-you-can</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Sun, 11 Oct 2026 10:08:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!W_vO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Every destination needs an eligibility rule, an acceptance test, and an owned way out.</em></p><div><hr></div><p>A model router should be explainable without asking a model to explain itself. An operator needs to know which evidence made a destination eligible, why the request went there, and what happened when its answer failed. A fluent rationale cannot substitute for those records. Four explicit tiers can make the system inspectable, provided the tiers describe operating contracts rather than a ladder every request must climb.</p><p>Consider a hypothetical assistant that answers engineers&#8217; questions from internal manuals and incident records. Some requests need an exact field, some need a short explanation, and some involve conflicting evidence or a decision the assistant cannot own. The proposed router has four destinations: deterministic code or an applicable cache; a small local or specialized decision model; an economical general model; and a frontier model or accountable human. This is a reference architecture, not a deployment I have measured.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W_vO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W_vO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!W_vO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!W_vO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!W_vO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W_vO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2261273,&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://signalovernoise.tech/i/219842420?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.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_!W_vO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!W_vO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!W_vO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!W_vO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F932cd2fb-11a3-41ac-9f78-1602434c5f92_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 request enters through an authenticated service, not directly through the router model. That service resolves the caller&#8217;s access, identifies the task, retrieves permitted source records, and constructs a bounded evidence packet. Include immutable source revisions, sensitivity labels, required output shape, deadline, and acceptance-rubric version. Keep absent fields explicit. If the question concerns two possible incidents, the system should ask which one before spending inference on an ambiguous packet.</p><p>Apply eligibility before ranking destinations. A privacy rule might permit only local processing for one document class, while another permits specific contracted endpoints. A model score cannot add an endpoint to that set. <strong><a href="https://www.openpolicyagent.org/docs">Open Policy Agent&#8217;s documentation</a></strong> separates policy decisions from enforcement: software supplies structured input and consumes the result. In this design, dispatch enforces that result, including during fallback. Missing authorization produces an owned hold or denial, not a more expensive interpretation.</p><p>Tier one handles what trusted code can finish. An incident timestamp comes from a permitted record through a formatter. A cached explanation can return only when caller scope, source revisions, output requirements, and relevant policy still agree. Recheck authorization at delivery; yesterday&#8217;s permission is not part of an immutable answer. Emit EXACT_FIELD_LOOKUP or CACHE_SCOPE_AND_REVISION_MATCH from the rule that actually passed. An invalid cache entry records CACHE_INVALIDATED and continues with the current evidence, rather than quietly supplying stale prose.</p><p>Tier two handles a bounded uncertainty that remains after those checks. A small local model could map the engineer&#8217;s wording to a supported task class or extract an incident identifier. A specialized decision model could choose among named destinations without drafting the answer. These are distinct jobs: selecting an explanation route does not itself complete an explanation request. Preserve the intermediate result, validate identifiers against accessible records, and emit BOUNDED_TASK_CLASS only when the configured operating boundary passes. Unrecognized language or conflicting selections produce CLASSIFIER_ABSTAIN and an explicit next state.</p><p>The threshold belongs to this workload. <strong><a href="https://github.com/lm-sys/RouteLLM">RouteLLM&#8217;s threshold guidance</a></strong> recommends using queries resembling incoming traffic and warns that the realized model split changes with the query distribution. That supports workload-specific evaluation, not a universal confidence cutoff. Choose tier-two boundaries against labeled development cases, then test untouched cases and costly errors separately. A well-formed probability or a valid extraction is evidence about the model&#8217;s output contract, not proof that the request has been understood correctly.</p><p>Tier three receives tasks requiring ordinary synthesis from sufficient evidence. Suppose an engineer asks how a documented configuration change affects one component. The economical general model receives the relevant approved excerpts and a fixed output contract, not the entire incident archive. Emit SUPPORTED_SYNTHESIS_WITHIN_CONTRACT when task shape, evidence sufficiency, context size, and permitted endpoint match. &#8220;Economical&#8221; is an evaluation result to establish for that workload, not a promise attached permanently to a model name or advertised token price.</p><p>Context locality constrains that choice. Keep retrieval and source ownership in the application, and pass references to retained artifacts between attempts rather than asking each model to rediscover them. A reference does not make evidence available to a remote model: dispatch must resolve and transmit the approved subset when needed. A summary may omit the qualification that determines the answer, so retain its source mapping and make original permitted excerpts available to the acceptance process. Carry forward useful work without treating an earlier model&#8217;s interpretation as a new trusted source.</p><p>A small model is not automatically a private model. &#8220;Local&#8221; needs an actual execution boundary; a hosted specialist may send the packet outside it. Before remote dispatch, select only necessary evidence, apply the approved disclosure policy, and validate the resulting packet against the question&#8217;s requirements. Redaction that removes the decisive fact creates REMOTE_PACKET_INSUFFICIENT. That branch holds for authorized review or uses an eligible local route. It does not send the original material to the frontier endpoint because the sanitized version was inconvenient.</p><p>Tier four separates difficult interpretation from authority. Conflicting but complete incident evidence might justify CONFLICTING_EVIDENCE_REQUIRES_FRONTIER if a permitted capable model has earned that task slice. Missing records still require records, not frontier reasoning. A request to approve an operational exception produces OWNER_DECISION_REQUIRED and goes to a named reviewer with the evidence, unresolved question, deadline, and permitted responses. Record acknowledgement and expiry. A waiting human queue is unresolved work, and a stronger model cannot become the absent owner.</p><p>Acceptance sits after every completed candidate, including a cache return. For this assistant, require the applicable revision, supported factual claims, preserved qualifications, correct access scope, and timely delivery. Deterministic checks can verify identifiers and citation targets; semantic support needs an appropriate evaluator and independent sampling. An answer passing a schema check has not passed the entire rubric. If evidence is absent, record SOURCE_EVIDENCE_MISSING and request it. If interpretation fails with adequate evidence, record SEMANTIC_ACCEPTANCE_FAILED before considering an eligible stronger route.</p><p>The recovery budget covers the request, not each tier independently. For a first implementation, I would permit at most one additional generation attempt after an initial candidate fails, with the actual timeout and cost ceiling chosen by the workflow owner. This is a proposed policy, not a measured optimum. A transient read failure can use bounded backoff; an unsupported answer needs a different remedy. <strong><a href="https://docs.litellm.ai/docs/proxy/reliability">LiteLLM documents retries followed by fallback to another model group</a></strong>, but the application must preserve eligibility and acceptance across that transition.</p><p>Start another attempt only when the remaining deadline can accommodate execution and validation. Coordinate recovery in one layer instead of letting the client, gateway, and application each spend a fresh budget. <strong><a href="https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/">Amazon&#8217;s retry guidance</a></strong> warns that layered retries multiply load and that a timeout does not establish that side effects failed. This assistant is read-only; if tools later change state, reconcile ambiguous outcomes or use a documented idempotency contract before repeating them. Budget exhaustion emits RECOVERY_BUDGET_EXHAUSTED with an owner and next state.</p><p>Build the audit event from those actual checks. Record request identity, policy and model versions, protected evidence references, evaluated routing features, selected branch, acceptance outcome, attempt parentage, and attributable cost and elapsed time. Reason codes come from application-controlled transitions, not a generated story about hidden deliberation. Keep rejected candidates and fallback history. Limit access and retention for the protected references; an audit log should not become a second, less controlled incident archive.</p><p>The tiers need not execute in sequence. A known owner decision should bypass generation. A task already evaluated as difficult can go directly to an eligible frontier model. Test the complete transitions against a capable single-model baseline and a simple rule, including stale permissions, revoked cache access, missing evidence, classifier abstention, timeout, and an unacknowledged review request. Promote only the slices that clear the same acceptance and containment gates. The router earns its complexity when every delivered answer and every stopped request has a traceable reason and an accountable owner.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Fallbacks Can Hide a Broken Router]]></title><description><![CDATA[Recovery should preserve the evidence of what failed before the answer arrived.]]></description><link>https://signalovernoise.tech/p/fallbacks-can-hide-a-broken-router</link><guid isPermaLink="false">https://signalovernoise.tech/p/fallbacks-can-hide-a-broken-router</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Sat, 10 Oct 2026 10:34:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_wOf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Recovery should preserve the evidence of what failed before the answer arrived.</em></p><div><hr></div><p>A fallback can keep the service working while the router gets worse. The user receives an acceptable answer, the availability chart stays green, and the primary destination keeps failing underneath. Automatic recovery has done useful work. It has also removed the symptom that would have forced somebody to investigate the first choice.</p><p>Yesterday&#8217;s scorecard asked whether a route deserves traffic. Once it has traffic, the fallback path can change what the scorecard appears to measure. A request configured for an economical model may finish on a more capable replacement. If the report credits the requested model with the delivered result, the operator learns that the economical route is reliable while paying for a different service. The unit of observation needs to survive the switch.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_wOf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_wOf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!_wOf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!_wOf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!_wOf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_wOf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2367981,&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://signalovernoise.tech/i/219709226?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.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_!_wOf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!_wOf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!_wOf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!_wOf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e677e95-d69d-453b-bc5d-bf1000f8ee1a_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Consider a hypothetical assistant that answers engineers&#8217; questions from approved manuals. Its primary deployment handles routine lookups; a second approved deployment can recover transient failures. The acceptance check requires the applicable document revision, supported claims, and delivery before a deadline. These are proposed operating conditions, not a deployment or benchmark performed here. Recovery is valuable only while those conditions remain intact.</p><p><strong><a href="https://docs.litellm.ai/docs/proxy/reliability">LiteLLM&#8217;s fallback documentation</a></strong> gives the mechanism a concrete shape: a call that fails after configured retries can move to another model group. It also documents separate context-window and content-policy fallback settings. Those branches deserve separate review because their causes differ. A larger context window may address an oversized evidence packet; an alternate provider does not automatically resolve a policy restriction or an answer that lacks support.</p><p>The gateway sees a provider error more readily than a plausible wrong answer. An answer with unsupported citations can return successfully and require application-level rejection. Record that rejection as a quality failure before choosing a remedy. Missing source material should lead to an evidence request or owned hold; a stronger model cannot retrieve a document the application never supplied. Treating every failure as an invitation to spend more conceals defects outside inference.</p><p>Start with one request identifier and attach each attempt to it. Preserve the requested route, policy version, attempted destination, selection reason, attempt number, failure class, fallback destination, and final serving destination. Record acceptance separately, including the rubric version and whether correction was required. Timing and cost belong to each attempt and to the completed request. A final success event should close the history, not replace it.</p><p>This does not require keeping every prompt in an analytics database. Use protected artifact references and bounded error codes where those provide enough diagnostic evidence. Limit access and retention for sensitive content. Keep request identifiers in traces or detailed records rather than turning each identifier into a metric label. The useful aggregate answers are how often a route needed rescue, what caused it, and whether the rescue preserved the task contract.</p><p>Cost attribution needs both destinations. Charge the primary policy for the complete sequence it initiated, while retaining each deployment&#8217;s actual consumption for billing and diagnosis. A timed-out attempt may have incurred charges even when no answer arrived; reconcile known usage with billing and label unresolved charges. If the dashboard counts only the final model&#8217;s tokens, it loses wasted work. If it assigns every charge to the requested model, it hides where the money went.</p><p>The latency distortion is easier to see with constructed timing. Suppose a primary attempt times out after four seconds, backoff takes one second, and the fallback finishes in two seconds. With no other work or overlap, the user waited seven seconds. Reporting the final call as a two-second response removes the delay that triggered it. These numbers illustrate accounting, not measured model performance, and actual end-to-end timing must include retrieval and validation too.</p><p>Build latency distributions from completed request durations rather than adding provider percentiles. A percentile from one population cannot be added to a percentile from another to recover the combined request tail. Separate direct completions, fallback completions, failed requests, and deadline misses, then show the overall workload distribution as well. <strong><a href="https://sre.google/sre-book/monitoring-distributed-systems/">Google&#8217;s SRE guidance</a></strong> distinguishes successful and failed request latency and warns that averages conceal slow tails. A fallback that eventually returns can still violate the deadline.</p><p>Provider comparisons need the same care. The fallback population contains requests that already failed somewhere else; it may carry longer inputs, prior delay, or harder questions. Comparing its acceptance rate with the primary&#8217;s easy direct completions confounds the destination with the work it received. Retain those operational cohorts, but use controlled paired cases with the same permitted evidence and rubric when comparing capabilities. A rescue rate is not a clean model ranking.</p><p>An increase in fallbacks is therefore a diagnostic question, not an automatic indictment. A brief provider outage, a changed traffic mix, a bad context limit, and a poorly chosen primary route can all raise it. Inspect failure classes and task slices before changing the router. Compare with a baseline that accounts for time of day and load when those matter. Tie an investigation threshold to the workflow&#8217;s tolerable cost and delay rather than copying a universal percentage.</p><p>Retry ownership matters when several layers can recover. The client, application, gateway, and provider SDK may each retry without seeing the others&#8217; budgets. <strong><a href="https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/">Amazon&#8217;s guidance on timeouts and retries</a></strong> explains how layered retries multiply load and how backoff and jitter reduce synchronized pressure. Give the request an overall deadline and a bounded recovery budget, with one layer responsible for coordinating attempts. Do not begin another call when too little time remains to complete and validate it.</p><p>A timeout also leaves an uncertain outcome when the route can execute tools. The first attempt may have performed an operation before its response disappeared. A fallback must reconcile that state or use an idempotency mechanism before repeating the operation. Otherwise, the final answer can look successful while two changes occurred. Keep dispatch authority and side-effect verification outside a model&#8217;s assumption that the previous attempt failed.</p><p>The strongest objection is sensible: users should not absorb a provider incident when an approved backup can finish their work. Keep that recovery path. Visibility need not mean exposing an implementation log in the interface or paging somebody for every retry. Page on user impact or threatened capacity; use route-level records to investigate concealed degradation. Google explicitly identifies internal monitoring as a way to detect failures masked by retries. Recovery can protect the user while still leaving the operator evidence.</p><p>Exercise that evidence path in a controlled environment. Make the primary return a transient error, exceed its context limit, produce an unsupported answer, and time out after a simulated side effect. State the expected fallback, hold, or denial for each case, then check both the final result and the complete attempt history. These are proposed fixtures, not tests executed here. Verify that a recovered request retains its original reason and failure, and that an exhausted budget leaves an owner and next state.</p><p>Repeated rescue should eventually force a routing decision. Repair the configuration when the evidence points to a configuration defect; move an eligible task slice directly to the replacement when comparative evaluation justifies it. Hold work when no permitted destination clears the requirements. A backup that carries the service indefinitely may have become the real primary, and the policy should acknowledge that change. A fallback earns the name resilience when the operator can see what it rescued and fix what keeps needing rescue.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Model Router Scorecard: Quality, Cost, Latency, and Failure]]></title><description><![CDATA[A cheaper route earns traffic only after quality, deadlines, and failure boundaries survive review.]]></description><link>https://signalovernoise.tech/p/the-model-router-scorecard-quality</link><guid isPermaLink="false">https://signalovernoise.tech/p/the-model-router-scorecard-quality</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Fri, 09 Oct 2026 10:08:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!TXsl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>A cheaper route earns traffic only after quality, deadlines, and failure boundaries survive review.</em></p><div><hr></div><p>A router can save money and still fail its promotion review. The rejected candidate might answer routine questions well, finish most requests quickly, and produce an attractive average bill. None of that excuses sending a restricted document to an unapproved endpoint. A scorecard earns its place when it keeps that failure visible instead of averaging it away.</p><p>The routing argument needs a decision at the end: give this policy traffic, revise it, or keep the existing route. Quality, cost, latency, and failure belong on the same review record, but they cannot all be traded at the same exchange rate. I would use separate acceptance gates before comparing the candidates that survive. The cheapest eligible route can win; an ineligible route cannot buy its way back with savings.</p><p>Consider a hypothetical assistant that answers engineers&#8217; questions from internal manuals and incident records. Routine lookups, conflicting evidence, and restricted documents share an interface but have different acceptance conditions. Its scorecard compares three policies: one approved capable model, a simple rule that separates known lookups from difficult interpretation, and a learned router. These are proposed comparison arms, not systems benchmarked here. Each receives the same permitted evidence and is judged against the same task contract.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TXsl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TXsl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!TXsl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!TXsl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!TXsl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TXsl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2249721,&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://signalovernoise.tech/i/219549878?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.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_!TXsl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!TXsl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!TXsl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!TXsl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612b5372-14f4-457e-8073-ea0a068bb1dc_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Start the record with its identity. Name the workload, document revision, permitted destinations, model versions, routing configuration, evaluation window, and accountable owner. Keep the cases used to choose thresholds separate from those used to report the result. A scorecard without that context is hard to reproduce and easy to reuse after its assumptions expire. A change to the retrieval source can invalidate a result even when the router&#8217;s configuration stays unchanged.</p><p>Quality starts at the delivered answer. A routine lookup must cite the applicable manual and preserve its qualifications. An incident explanation must separate an observed event from a proposed cause. A missing record should produce an evidence request or an owned hold, rather than a plausible explanation. Matching a reference model choice is a useful routing diagnostic, but it does not establish that the resulting answer passed those requirements.</p><p>Report counts by task slice alongside the overall result. Keep a representative traffic set for the expected operating mix and a separate challenge set for conflicting revisions, incomplete records, and prohibited destinations. The challenge set tests specific boundaries; its proportions do not estimate their frequency in traffic. Record accepted coverage, rejected answers, and independently discovered errors among accepted answers. Otherwise, a router that declines most hard work can make its quality number look excellent while moving the burden to somebody else.</p><p><strong><a href="https://github.com/lm-sys/RouteLLM#threshold-calibration">RouteLLM&#8217;s project guidance</a></strong> recommends calibrating on queries resembling the incoming workload and warns that the realized model split changes with the query distribution. Its evaluation framework also supplies public benchmark comparisons. Those are useful starting points, not acceptance evidence for this assistant. A desired share of strong-model calls is a spending control; the scorecard must still show which requests became acceptable and which errors survived.</p><p>The cost gate uses the complete policy&#8217;s bill. Include routing, retrieval, generation, retries, fallback attempts, and active human correction within a stated accounting boundary. Preserve the spending on rejected work in the numerator when calculating cost per accepted result. Show the number of accepted results beside that ratio, and leave it undefined when none passed. Yesterday&#8217;s accounting argument becomes useful here because the review must decide whether savings survive the same quality gate.</p><p>Keep request spending separate from allocated infrastructure and maintenance. A low-volume workflow may spend more maintaining a learned router than it saves in inference. An organization might still choose it for a documented quality advantage, but that is a different justification. Record unknown charges and the billing reconciliation window. A precise-looking total built from incomplete records should remain an incomplete cost result.</p><p>Latency needs its own gate because a correct answer can arrive after it is useful. Measure from request arrival to accepted delivery, including retrieval, validation, retries, and any review queue. Show the distribution for completed requests and count deadline misses and unfinished requests separately. Do not let requests that never finished disappear from the timing record. Parallel work contributes to elapsed time through its actual execution path, not the sum of every component duration.</p><p><strong><a href="https://sre.google/sre-book/monitoring-distributed-systems/">Google&#8217;s SRE monitoring guidance</a></strong> explains why averages can conceal slow tails and why latency deserves attention even when a request eventually succeeds. In this assistant, a slow incident explanation might still be usable, while a late operational lookup might miss its purpose. Report timing by those task slices and by first-choice versus repaired completion. Choose the deadline from the workflow&#8217;s need before examining which candidate looks fastest.</p><p>Failure containment is the gate most likely to vanish behind a green success rate. Exercise a provider timeout, an exhausted retry budget, stale permissions, missing evidence, and an unavailable approved destination in a controlled test environment. These are proposed tests, not tests performed for this article. For each fixture, state the allowed result before execution and retain the observed route, held work, and recovery owner afterward. A fixture that merely produces some final answer has not proved containment.</p><p><strong><a href="https://docs.litellm.ai/docs/proxy/reliability">LiteLLM documents retries followed by fallback to another configured model group</a></strong>. That mechanism gives the test something concrete to exercise; it does not certify the replacement&#8217;s eligibility for the document. The assistant should keep restricted material within the approved destination set through every attempt. If that set becomes unavailable, the expected outcome may be an owned hold with a deadline. Successful failover is a failure when it crosses the boundary the original route was required to preserve.</p><p>Enforcement needs evidence beyond a scorecard row. <strong><a href="https://www.openpolicyagent.org/docs">Open Policy Agent separates policy decision-making from enforcement</a></strong>: software supplies structured input and consumes the decision. The application must actually constrain dispatch. Inspect that boundary and test its treatment of absent or stale inputs. An evaluation with no observed disclosure supplies evidence about those cases, but it is not proof that a learned router can replace the enforcement mechanism.</p><p>The review can now make a narrower decision than declaring one router best. Promote the routine lookup slice if it meets the declared quality, cost, deadline, and containment requirements. Keep disputed incident explanations on the existing route if the evidence remains weak. Hold promotion when the sample is too small, a costly error lacks coverage, or accounting is unresolved. The decision record should name the permitted slice, remaining exclusions, reviewer, and conditions that trigger another review.</p><p>There is a reasonable objection to four gates: measurement and review have costs too. A small service with a satisfactory single-model route may gain little from this comparison. Start with the few failure cases and constraints that would actually change the owner&#8217;s decision, then add detail where uncertainty remains. The scorecard is a record of evidence, not a demand to build an observability platform before answering a question. It should make a simpler baseline easier to defend when complexity earns nothing.</p><p>After promotion, retain the cases that justified it and a route back to the baseline. Revisit the decision when a model alias moves, permissions change, traffic shifts, or repeated repair starts consuming the savings. Name who can stop the candidate and what evidence they need. A promotion review is useful only if its failure conditions remain actionable after the meeting ends. Give the router traffic it has earned, and keep the authority to take that traffic back.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Cost per Accepted Answer Is the Routing Metric That Matters]]></title><description><![CDATA[Charge the failed attempts and the work of repair before declaring a cheaper route.]]></description><link>https://signalovernoise.tech/p/cost-per-accepted-answer-is-the-routing</link><guid isPermaLink="false">https://signalovernoise.tech/p/cost-per-accepted-answer-is-the-routing</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Thu, 08 Oct 2026 10:10:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!wCr9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Charge the failed attempts and the work of repair before declaring a cheaper route.</em></p><div><hr></div><p>A cheap model becomes expensive when somebody has to finish its answer. The first call can look like a routing win while the complete request accumulates another inference, repeated retrieval, and a review queue. A token-price comparison ends before those costs arrive. The useful unit is the work that passes an agreed acceptance test.</p><p>This week&#8217;s routing argument has moved from choosing an eligible destination to preserving progress during a handoff. The next question is whether the whole path earns its bill. Cost per accepted answer is total attributable operating cost for a defined request cohort divided by the number of answers that meet its requirements. Failed attempts belong in the numerator even though they contribute nothing to the denominator. With no accepted answers, report the spending and zero successes; the ratio is undefined.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wCr9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wCr9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!wCr9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!wCr9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!wCr9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wCr9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2333167,&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://signalovernoise.tech/i/219401373?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.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_!wCr9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!wCr9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!wCr9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!wCr9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cb871b9-e3dd-4315-8c04-1ded47f7ac8f_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Define acceptance before comparing routes. Consider a hypothetical documentation assistant that explains a software change from permitted source records. An answer must cite the applicable revision, support its explanation, preserve relevant qualifications, and arrive within the agreed deadline. A plausible paragraph or a successful HTTP response cannot satisfy that contract. If a person repairs the answer, record it as accepted after repair, with the repair charged to the route.</p><p>The denominator needs a boundary too. Count unique completed requests rather than every candidate response, retry, or intermediate artifact. Give a cohort enough time to finish, report unresolved requests separately, and retain abandoned work&#8217;s spending. Otherwise, one route can look efficient because its expensive cases are still waiting for review. Publish acceptance rate and coverage beside the ratio so a system cannot improve its apparent economics by dropping difficult work.</p><p>Here is constructed arithmetic, not a benchmark or a current price quote. Send one hundred requests through an economical model at one cent each. Forty require a stronger-model attempt costing another five cents each, and ninety requests eventually pass the fixed acceptance test. Model spending is three dollars, or about 3.33 cents per accepted answer. Sending all one hundred directly to the stronger model costs five dollars; if ninety-five pass, that is about 5.26 cents each.</p><p>Now assume the cascade also requires twenty one-minute reviews, while the direct route requires five. At an illustrative labor allocation of sixty cents per minute, those reviews add twelve dollars and three dollars respectively. Keep the same final acceptance counts, including any reviewer repairs: the cascade costs about 16.67 cents per accepted answer, against 8.42 cents for the direct route. The first model&#8217;s cheaper call survived the comparison. The route&#8217;s advantage did not.</p><p>Those assumptions cannot tell you which model to buy. They expose what the comparison has to include. Change first-pass acceptance, escalation frequency, reviewer effort, or the price of either call, and the result can reverse again. A review may be required by policy regardless of model quality; charge that common requirement consistently. Treat additional correction caused by a route as a separate burden rather than declaring every minute of review avoidable.</p><p>The surrounding software can move the bill even with the model held fixed. Liu and Han&#8217;s October 3 preprint, <strong><a href="https://arxiv.org/html/2610.04433v1">What Does a Harness Buy? Tokens, Mostly</a></strong>, reports cost per task differing by up to threefold across coding-agent harnesses under a common price ledger. The study pins Claude Code 2.1, mini-SWE-agent 2.4.6, and OpenCode 1.18 revisions, uses offline SWE-bench Verified tasks and a 300-call budget, and examines both locally served Qwen models and vendor API models. Its monetary analysis uses the API arms; local models contribute token counts. Repeated prompt and tool-schema input helps explain the spending differences. These are author-reported preprint results, not measurements reproduced here or proof about this documentation assistant.</p><p>Build the ledger around a request identifier that survives every attempt. Record the routing-policy version, attempted destination, reason code, model revision when available, and acceptance-rubric version. Attach retrieval, generation, validation, tool execution, and review as separate events with parentage. Each event needs its outcome, attributable cost, and elapsed time. The final destination should not inherit a clean bill merely because earlier attempts disappeared into another log.</p><p>Gateway accounting supplies part of that record. <strong><a href="https://docs.litellm.ai/docs/proxy/cost_tracking">LiteLLM&#8217;s spend-tracking documentation</a></strong> describes calculated response costs and spend records, and recommends reconciling discrepancies through time ranges, token categories, and pricing data. That is useful input to the application ledger. It does not establish whether an answer passed, how long a reviewer spent correcting it, or what a paid retrieval service charged. Reconcile the model component with actual billing and keep unknown costs visible.</p><p>Retries need distinct failure labels. A transient transport failure, an invalid output, unsupported claims, and missing source evidence demand different remedies. <strong><a href="https://docs.litellm.ai/docs/proxy/reliability">LiteLLM&#8217;s fallback contract</a></strong> can move to another model group after configured retries. Application quality failures still need an explicit path. Estimate retry probability by failure class and attempt number; the next attempt is conditional on the previous failure, not another average request drawn from the whole workload.</p><p>Tool-call waste deserves its own field. If the economical route retrieves the same records three times, its lower generation bill has purchased extra database work and delay. Mark which retrieved artifacts remain usable by the next attempt. Charge repeated execution where it occurs and avoid charging a shared retrieval twice. A tool timeout also needs an uncertainty state: reconcile whether an operation completed before reissuing it, especially when another attempt could duplicate a side effect.</p><p>Cache reuse changes the path more substantially. <strong><a href="https://docs.litellm.ai/docs/proxy/caching">LiteLLM distinguishes response caching</a></strong>, which can return a stored response without another model call, from provider prompt caching. The ledger should preserve that distinction, including lookup, storage, and validation costs. Reuse only when authorization, source revision, and answer requirements still agree. Report cold and warm traffic separately as well as the expected traffic mix; a benchmark full of repeats can flatter a route serving mostly new questions.</p><p>Elapsed time remains a separate constraint. Track time from request arrival to accepted delivery, with retrieval, inference, escalation, active review, and queue waiting visible. Waiting is not automatically billable reviewer time, and parallel event durations cannot simply be added to obtain wall-clock latency. Inspect the median and slow tail, then record how often the route misses its deadline. An answer that becomes correct after the user needed it has failed a time-bounded contract.</p><p>There is a limit to what this ratio can govern. An unsupported statement that slips past a weak check makes the route look both cheaper and more successful. Audit accepted outputs independently, distinguish costly error classes, and account for later retractions within a stated observation window. Keep authorization and high-impact error limits as hard constraints. A low average operating cost cannot purchase permission to cross them.</p><p>Compare policies on the same permitted workload with the same rubric, deadlines, and accounting boundaries. Preserve task slices such as exact lookups, conflicting evidence, missing records, and long context; changing their proportions can change the winner. Run paired comparisons where practical and repeat enough cases to expose variability. Include a capable single-model baseline and a simple rule before crediting a learned router for savings. A router recommendation alone cannot reveal the outcome of an alternative that was never executed.</p><p>I would start with one bounded workflow and a ledger that can explain every rejected or repaired answer. Separate marginal request spending from allocated infrastructure and maintenance, then show both when making an adoption decision. Replace the current route only when the candidate clears the same quality and containment requirements at a better complete operating cost. The cheapest call has earned nothing until the request is finished.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[SAGE Router: Should the Agent Work Alone, Recruit, or Hand Off?]]></title><description><![CDATA[The useful routing decision accounts for the work already done and the evidence still missing.]]></description><link>https://signalovernoise.tech/p/sage-router-should-the-agent-work</link><guid isPermaLink="false">https://signalovernoise.tech/p/sage-router-should-the-agent-work</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Wed, 07 Oct 2026 09:51:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1dDL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The useful routing decision accounts for the work already done and the evidence still missing.</em></p><div><hr></div><p>Recruiting another agent can make a task worse even when that agent is better at the remaining work. The new executor needs usable artifacts, permissions, and enough time to recover the context. Someone must own the dependencies and evaluate what comes back. SAGE Router makes those costs part of an inspectable decision about continuing, collaborating, or handing off.</p><p>That is a different problem from choosing a model endpoint. A model router can switch providers while the application keeps the task. An agent handoff can change who owns the work, which tools can reach its evidence, and how much progress survives. Sprix SAGE Router is interesting because it takes those differences seriously. Its strongest idea is evaluating the next execution configuration from a checkpoint rather than starting the comparison over with every participant&#8217;s advertised skills.</p><p>The version boundary matters before examining that idea. The project published <strong><a href="https://github.com/wang2122/sprix-sage-router/releases/tag/v0.3.0">v0.3.0 on August 28</a></strong>, with attached distributions, while PyPI publication remained gated in its release notes. The PyPI project endpoint still returned 404 during this review. Current main also declares 0.3.0 but includes a later checkpoint-aware change than the tag. This article examines <strong><a href="https://github.com/wang2122/sprix-sage-router/tree/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0">main at commit bdc9c24</a></strong>, not an assumption that every feature discussed ships in the tagged wheel.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1dDL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1dDL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!1dDL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!1dDL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!1dDL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1dDL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e13d902a-747e-4670-9866-2b4b1033b807_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2161997,&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://signalovernoise.tech/i/219235777?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.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_!1dDL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!1dDL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!1dDL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!1dDL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe13d902a-747e-4670-9866-2b4b1033b807_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 <strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/pyproject.toml">package metadata</a></strong> requires Python 3.10 or newer and declares no runtime dependencies. This is ordinary Python routing code, not an inference engine requiring a particular model or accelerator. The project labels it an alpha research preview under the MIT license. A pinned source checkout is the reproducible starting point for examining this revision; neither the package version string nor a successful installation establishes operational readiness.</p><p>Consider a hypothetical documentation-repair task. An incumbent has finished collecting the relevant source material and is partway through correcting an example. The remaining requirements include checking that example and producing a revised explanation. Some work can proceed in parallel; the final explanation depends on the checked example. A general reputation score might select the strongest writer and discard the incumbent&#8217;s half-finished correction. The useful question is what that writer can complete from the artifacts actually available.</p><p>SAGE accepts a requirement graph, budget, deadline, and permission requirements alongside live execution state. That state identifies completed requirements, active assignments, the in-flight requirement, partial progress and quality, and artifact portability. Its <strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/ALGORITHM.md">algorithm design</a></strong> distinguishes three modes: SELF keeps the incumbent working alone; COLLABORATE retains its ownership while recruiting peers; HANDOFF transfers ownership to one peer. Completed nodes leave the remaining-work calculation while dependency effects survive.</p><p>Portability changes the comparison. Keeping a healthy current owner preserves the modeled completed fraction of its in-flight requirement. Moving that requirement discounts reusable progress by the artifact&#8217;s portability. A checked file may transfer cleanly; an undocumented tool session may not. The caller supplies those observations. SAGE cannot discover whether a claimed checkpoint is usable by inspecting a progress number, so the documentation-repair service needs artifact checks before it lets that number influence ownership.</p><p>The current assignment logic also repairs a tempting shortcut. Only the assigned owner contributes coverage for a requirement; an idle teammate does not raise predicted quality merely by joining. The router jointly searches teams, requirement owners, and schedules using bounded beam search. Work on one agent serializes, while independent work on different agents can overlap. A slightly weaker checker can therefore be a useful collaborator if assigning the check frees the incumbent to complete other work within the deadline.</p><p>This is the practical meaning of marginal contribution. Another excellent writer who receives no useful assignment adds little to the documentation task. A checker covering an otherwise weak requirement can change its prospects. The <strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/sprix_sage.py">implementation</a></strong> combines assigned coverage, bottlenecks, trust, and coordination with predicted success and resource costs. Its bounded search is a heuristic, not proof of a globally optimal coalition. The weights and capability estimates remain assumptions to evaluate against the work.</p><p>Trust follows requirements rather than traveling intact with an agent&#8217;s name. SAGE combines global reliability with evidence conditioned on the requirement, then adjusts advertised capability and bid confidence. After execution, granular agent or requirement scores carry stronger credit than an ambiguous overall team result. Pair synergy updates require explicit pair evidence. That is a useful accounting discipline: a successful documentation bundle does not establish that every participant can repair code or that two participants caused each other&#8217;s improvement.</p><p>Learning still needs a judge. The router&#8217;s online success predictor and reliability beliefs update from supplied outcomes; their neat numeric interface cannot certify those outcomes. An agent grading its own artifact can contaminate the next routing decision. Use an evaluator with an acceptance rubric and retain failed checks, actual costs, and actual elapsed time. Source inspection shows the feedback mechanism exists. It does not demonstrate calibrated predictions on this hypothetical workflow, and no endpoint benchmark was performed for this article.</p><p>The feasibility behavior deserves more attention than the launch table. Permissions, availability, and failure state filter agents before ranking. However, the default can return an authorized degraded plan when no route satisfies budget and deadline, marking it infeasible with constraint violations. Set allow_degraded=False when those limits must stop the request. The <strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/docs/OPERATIONS.md">operations guide</a></strong> makes that distinction explicit. A returned object is not evidence that the task can proceed within its limits.</p><p>The transport adapter exposes another boundary worth checking in code. It combines declared Agent Card skill identifiers with locally supplied numeric evidence, then converts a decision into an execution plan. That plan contains assignments, dependencies, ownership, estimated resources, and rationale. It does not carry the decision&#8217;s feasibility flag or constraint-violation list. The executor must inspect the original decision before converting or dispatching it, or preserve those checks separately. A convenient serialization step can otherwise lose the warning the operator needed (<strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/sprix_a2a.py">adapter source</a></strong>).</p><p>The adapter also does not authenticate endpoints, verify signatures, transmit tasks, or enforce isolation. Its <strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/docs/INTEGRATION.md">integration guide</a></strong> assigns secure transport, cancellation, timeouts, idempotency, and artifact evaluation to the surrounding client. Learning snapshots preserve beliefs and model parameters, not running tasks or artifacts. An external lifecycle must acknowledge the new owner, fence the old executor where necessary, and recover interrupted work without duplicate effects. A permission label inside the router cannot grant the credential that executes the plan.</p><p>The synthetic studies make the ideas inspectable without proving the adoption case. The <strong><a href="https://github.com/wang2122/sprix-sage-router/blob/bdc9c24f0f7e170d807ffaeb630a478a5810b8d0/docs/BENCHMARKING.md">benchmarking guide</a></strong> separates checkpoint replay, requirement-conditioned trust, and independent-task regression. Structurally separate evaluators help challenge the router&#8217;s own scoring assumptions. They are still authored within the project, with synthetic agents and outcomes. Reproducing those tables would verify that experiment, not show superiority on authenticated heterogeneous endpoints. The current open issue and pull-request review supplied no external production validation either.</p><p>A fixed executor may remain the better design for a small documentation workflow. I would compare that baseline with SAGE in offline replay and shadow decisions, including poor portability, stale quotes, missing permission, failed incumbents, and impossible deadlines. Count accepted artifacts, wasted work, ownership errors, and recovery time across the whole route. Hold protected work for an accountable owner when evidence or constraints fail. SAGE earns a bounded experiment because it asks what survives the switch. Give it better evidence before giving its handoff real consequences.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Best Model Router Sometimes Chooses No Model]]></title><description><![CDATA[Skipping inference is useful only when the request still has an owner and a next state.]]></description><link>https://signalovernoise.tech/p/the-best-model-router-sometimes-chooses</link><guid isPermaLink="false">https://signalovernoise.tech/p/the-best-model-router-sometimes-chooses</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Tue, 06 Oct 2026 10:42:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qrUj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Skipping inference is useful only when the request still has an owner and a next state.</em></p><div><hr></div><p>A router that can only choose a model has already decided to spend money answering. It can compare providers, capabilities, and latency while missing the cheaper decision: this request should not reach inference yet. The answer may already exist, the input may be incomplete, or nobody may have authority to act. A better destination list includes those conditions before model selection begins.</p><p>Yesterday&#8217;s routing argument put policy ahead of the provider dropdown. The next step is to give that policy somewhere concrete to send unfinished work. &#8220;No model&#8221; covers several different outcomes: complete the request through code, return an applicable cached result, ask for missing context, defer until a dependency recovers, deny a prohibited operation, or hand a decision to its owner. Collapsing them into one refusal makes the interface simpler by hiding the job that remains.</p><p>Consider a hypothetical release-preparation service. An engineer asks it to explain the changes in a build and prepare a deployment request. The service receives an authenticated identity, a project, a build identifier, and the engineer&#8217;s message. It can read permitted release records and produce a proposed explanation. Deployment approval belongs to a separate owner. This is a reference design, not a system I have benchmarked or deployed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qrUj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qrUj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!qrUj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!qrUj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!qrUj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qrUj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1902211,&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://signalovernoise.tech/i/219078622?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.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_!qrUj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!qrUj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!qrUj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!qrUj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48249ba-d9de-4dd6-b1bf-bf1437de312e_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Start with what the service can establish without interpreting prose. Does the caller have access to that project? Does the build exist? Has an identical preparation request already completed? If access is denied, the protected operation stops. If identity cannot be verified because a dependency failed, retain an unresolved request rather than inventing an access verdict. <strong><a href="https://www.openpolicyagent.org/docs/policy-language#default-keyword">Open Policy Agent&#8217;s default-rule documentation</a></strong> demonstrates an explicit default allow value of false. The application still has to distinguish a policy denial from its inability to obtain the evidence for a decision.</p><p>A completed result can avoid generation altogether. <strong><a href="https://docs.litellm.ai/docs/proxy/caching">LiteLLM documents response caching</a></strong> that returns a stored response instead of calling the model again. That differs from retaining prompt context to make another inference cheaper. In this release service, reuse needs a stronger contract than matching the engineer&#8217;s wording: project and access scope, immutable build and source revisions, output requirements, and relevant policy version must agree. Current authorization must still pass before the cached explanation leaves storage.</p><p>Freshness follows the thing being answered. An explanation of an immutable build can remain applicable while an approval or environment status changes. Keep those records separate, with invalidation rules for each. A cached deployment approval cannot substitute for checking today&#8217;s permission and target state. Even an exact textual match is insufficient when the facts behind the text have changed. A semantic near match creates another uncertainty to evaluate, not a shortcut around those checks.</p><p>Some requests need no stored model output either. A build timestamp, artifact identifier, or list of changed files can come from trusted records through a maintained formatter. A model earns its call when the engineer needs interpretation, such as connecting several verified changes into a useful release explanation. The route should preserve that distinction. Do not invoke a language model to decorate an exact lookup merely because every other branch speaks in paragraphs.</p><p>Missing context creates a different destination. &#8220;Prepare the release for the payments service&#8221; is incomplete if two builds are eligible. Return the permitted candidates and ask which build the engineer means. An explicit field validator can trigger that question without inference. If language creates the ambiguity, a classifier or decision model may help identify it, but its own call belongs in the cost ledger. &#8220;No generative model&#8221; and &#8220;no inference&#8221; are different claims.</p><p>Clarification needs an exit condition. Persist the missing field, the original request, and enough authorized state to resume when the answer arrives. Validate the supplied build rather than treating any reply as permission to continue. If the user never responds, expire the preparation request visibly. Repeatedly asking an open-ended model whether it now understands can consume more work than a narrow form and still leave the required identifier unresolved.</p><p>A specialist judge can help with the remaining semantic branch. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/patterns/intent-routing">intent-routing example</a></strong> sends different classes to deterministic handlers, specialist LLMs, or humans. The useful architectural feature is that model generation is only one destination. Its example cutoffs are not measured operating thresholds for this release service. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/confidence">confidence definition</a></strong> describes distribution concentration; a decisive result cannot establish that the build evidence is complete or the caller can approve deployment.</p><p>Defer when the missing prerequisite belongs to the system. If the source-record service is unavailable, keep the request pending with a bounded retry budget, an expiry, and an owner after retries end. Tell the engineer what is pending and when to expect another state change. Sending the same incomplete packet to a more capable model cannot recover the unavailable records. A timeout should become an observable dependency failure, not a confident explanation of a release nobody inspected.</p><p>Human review is appropriate when the evidence exists but the decision requires judgment or authority the service lacks. A request to waive a deployment condition can go directly to the designated release owner. Send the exact build, relevant condition, proposed exception, and unresolved question. Track acknowledgement and elapsed wait, with a backup owner if the deadline passes. A human destination with no service expectation is an unmonitored backlog, and a growing backlog eventually becomes user harm.</p><p>Durable pause is available machinery. <strong><a href="https://docs.langchain.com/oss/python/langgraph/interrupts">LangGraph&#8217;s interrupts documentation</a></strong> describes saving graph state through a checkpointer and waiting for external input before resuming. It also warns that the interrupted node restarts from its beginning, so preceding side effects can repeat. Put irreversible execution behind validated approval and protect it against duplicate execution. Persistence preserves the workflow&#8217;s place; it does not supply a reviewer, a response deadline, or permission to deploy.</p><p>Refusing is not automatically the safer outcome. A needless denial can block a legitimate release; an indefinite deferral can strand a correction the organization needs. Distinguish the harm of an unauthorized action from the harm of delayed permitted work. Hold the protected deployment while allowing authorized preparation or status retrieval to continue when those tasks are independent. An appeal path and a visible deadline belong beside the denial rule, especially when automated interpretation helped trigger it.</p><p>Evaluate this router with abstention included. Geifman and El-Yaniv&#8217;s <strong><a href="https://arxiv.org/abs/1705.08500">2017 selective-classification paper</a></strong> studies the tradeoff between prediction risk and coverage by allowing rejection. Its image-classification results do not certify a release router. The transferable question is how errors change as automatic coverage changes. Report errors among accepted cases, automatic coverage, unnecessary denials, clarification completion, deferred-request age, and human resolution time. A system can lower accepted-case error by sending nearly everything away while making the overall service worse.</p><p>The test fixtures should include a repeated request after access revocation, two valid builds, an unavailable source service, a stale approval, an exception nobody owns, and an ordinary exact lookup. Check the whole resulting state transition, including the reply and eventual resolution. Choose any semantic thresholds on development cases, then evaluate untouched cases. No universal cutoff or savings percentage follows from this design; reduced generation spends less only if routing, retries, and follow-up work do not consume the difference.</p><p>I would begin with explicit rules and a small set of named outcomes before adding a learned router. Keep completed-through-code and completed-through-cache distinct from waiting-for-context, waiting-for-dependency, waiting-for-owner, and denied. Record why each branch occurred and whether the request ultimately finished. That ledger makes it possible to compare against one approved capable model without rewarding a router for dropping the work it was supposed to handle.</p><p>The consequential decision is who owns the request after inference stops. A cache hit can close it. A clarification must reopen it when the missing field arrives. A deferral needs a clock, and a human handoff needs a person who accepts the work. Add those destinations before tuning which model wins. If the router chooses no model, it still owes the user a next state.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[A Model Router Is a Policy Engine with a Benchmark Problem]]></title><description><![CDATA[The cheapest allowed route still has to pass the workload that gives it consequences.]]></description><link>https://signalovernoise.tech/p/a-model-router-is-a-policy-engine</link><guid isPermaLink="false">https://signalovernoise.tech/p/a-model-router-is-a-policy-engine</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Tue, 06 Oct 2026 10:39:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!DMuE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The cheapest allowed route still has to pass the workload that gives it consequences.</em></p><div><hr></div><p>A model router decides which compromises your users will live with. Sending a request to a cheaper endpoint trades some expected capability for a smaller bill. Sending it elsewhere during an outage trades continuity against the properties of the replacement. Those choices encode priorities about quality, latency, privacy, and acceptable failure, even when the configuration calls them a threshold.</p><p>Yesterday&#8217;s decision ladder asked which primitive deserves the job. Routing adds a harder question: under today&#8217;s conditions, which available destination can meet this request&#8217;s requirements? A model name alone cannot answer it. The destination includes its context, tools, operating limits, and failure path. A router becomes a policy engine in the architectural sense when it turns those requirements into executable choices; that does not make its learned predictions deterministic or authoritative.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DMuE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DMuE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!DMuE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!DMuE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!DMuE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DMuE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2302794,&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://signalovernoise.tech/i/219077519?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.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_!DMuE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!DMuE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!DMuE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!DMuE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2251d538-a717-44a7-8a0b-4e336168d338_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Consider a hypothetical internal-document assistant. It answers routine questions from approved manuals and helps engineers reconcile conflicting incident records. Some documents may leave the organization&#8217;s environment; others must stay inside a designated deployment. The assistant also has a response deadline and a monthly spending ceiling. A semantic judgment that the request looks easy cannot settle any of those boundaries.</p><p>Start by constructing the allowed destination set from trusted document classifications, caller permissions, deployment approvals, and current availability. Apply that boundary before exposing the request to a hosted router, too. Otherwise, the service can disclose the material while deciding where the material should go. <strong><a href="https://www.openpolicyagent.org/docs">Open Policy Agent&#8217;s documentation</a></strong> illustrates the separation between evaluating policy against structured input and enforcing the decision. The application must enforce the eligible set before a learned ranker selects within it.</p><p>That still leaves a prediction problem. The permitted small model may answer a routine manual question adequately, while a disputed incident needs more interpretation. RouteLLM supplies a concrete research baseline: its <strong><a href="https://arxiv.org/abs/2406.18665">paper</a></strong> learns strong-versus-weak model routing from preference data and evaluates quality and cost on public benchmarks. That work makes learned routing worth testing. It does not establish an acceptance boundary for this assistant&#8217;s documents, deadlines, or expensive mistakes.</p><p>The project&#8217;s own <strong><a href="https://github.com/lm-sys/RouteLLM#threshold-calibration">threshold-calibration guidance</a></strong> recommends using queries resembling incoming traffic. Its example targets a chosen share of calls to the stronger model, and it warns that the realized share changes with the actual query distribution. Setting a traffic share is not the same as demonstrating a quality floor. A copied threshold can preserve the configuration syntax while changing the service you deliver.</p><p>Routing accuracy alone hides the central ambiguity: correct according to which label? If two allowed models produce acceptable answers, either route may satisfy the task. Agreement with a label that always names the stronger model could punish a cheaper success. Conversely, matching the reference destination says nothing about whether its answer cited the applicable manual revision. Evaluate the chosen route&#8217;s outcome, and keep route-label agreement as a diagnostic with a stated meaning.</p><p>Averages can bury the mistake that matters. Imagine a constructed test with 950 routine questions and 50 questions about conflicting records. A router accepts all the routine cases and misses ten of the difficult ones. Its aggregate success rate is 99 percent, while success on the difficult slice is 80 percent. These are illustrative counts, not measurements. If the missed cases produce unsupported incident explanations, the large routine population has made the chart reassuring without making that failure tolerable.</p><p>The test set therefore needs the work&#8217;s actual shape: short lookups, long evidence packets, conflicting revisions, missing documents, unfamiliar terminology, and requests that cannot use an external endpoint. Preserve a representative traffic set for overall cost and latency. Maintain a separate challenge set for rare costly errors, then report its results separately rather than pretending its proportions match production. Establish expected evidence and acceptable responses before seeing which route wins.</p><p>For this assistant, a routine answer passes only when it uses the permitted, applicable document and supports its claims. An incident explanation must distinguish observed facts from proposed causes; missing evidence should trigger a request for records or owned review. Choose thresholds on development cases and report results on untouched cases, including accepted coverage and error counts by slice. A finite test with no observed policy violations is evidence about those fixtures, not permission to remove the enforcement boundary.</p><p>Availability creates a second kind of routing. <strong><a href="https://docs.litellm.ai/docs/routing">LiteLLM&#8217;s routing documentation</a></strong> describes deployment selection by weight, rate limits, latency, and cost, alongside retry behavior. These mechanisms help distribute requests among configured destinations. They do not establish that a fast available deployment can answer the document question correctly. Keep operational selection and task-quality selection visible as separate decisions, even when one gateway implements both.</p><p>Context locality belongs in that decision. A remote model&#8217;s generation speed can be outweighed by transferring and processing a large evidence packet. A destination with the relevant permitted context already available may finish sooner, while one with missing retrieval access may be unable to finish at all. Treat those as hypotheses to measure with complete requests. Record time to an accepted response, including retrieval and validation, and inspect slow-tail behavior alongside the median.</p><p>An observable reason should describe the branch the application took. Record the policy version, candidate deployments, exclusion codes, routing features, score and threshold when used, selected destination, and eventual acceptance. A code such as restricted-context or quality-escalation can identify a concrete condition without inviting the model to invent a persuasive explanation afterward. Protect the underlying records and apply the same access boundaries to telemetry. The log needs enough evidence to diagnose the route without becoming another document leak.</p><p>Fallbacks must preserve the requirements that made the first destination eligible. If the designated internal deployment times out, retry within a bounded budget or use another approved internal destination that passes the same task gates. If none exists, retain the request for an owner with a response deadline. An external endpoint&#8217;s availability does not relax the document boundary. Record the failed attempt, replacement, elapsed time, accumulated cost, and final result together so resilience cannot conceal a bad first choice.</p><p>There is a sound objection to this machinery: a low-volume assistant may be easier to operate with one approved capable model. That should be the baseline, alongside a simple rule using task type and context size. A learned router earns its dependency when it improves complete accepted work while preserving quality and containment. Include the router&#8217;s own inference, retries, retrieval, and reviewer effort in the comparison. A lower average model bill can lose to the maintenance and correction bill it creates.</p><p>I would introduce the candidate router in shadow mode before letting it redirect user requests. Compare its proposed branches with independently evaluated destination outcomes on representative permitted cases. Shadow suggestions alone cannot reveal what an uncalled model would have answered; that requires controlled comparative runs with the same evidence and acceptance rubric. Promote only the task slices that meet the agreed requirements, retain a rollback path, and recheck them when models, policies, document sources, or traffic change.</p><p>The owner of the assistant should be able to explain why a request took its route and show what happened when that route failed. That explanation begins with requirements, survives a benchmark built from the work, and ends with an accountable fallback. Give the router a policy you can inspect before giving it traffic you cannot afford to misroute.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Decision Ladder: Rules, Classifiers, Decision Models, and LLMs]]></title><description><![CDATA[A harder request earns a different tool only when that tool can resolve the remaining uncertainty.]]></description><link>https://signalovernoise.tech/p/the-decision-ladder-rules-classifiers</link><guid isPermaLink="false">https://signalovernoise.tech/p/the-decision-ladder-rules-classifiers</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Sun, 04 Oct 2026 09:40:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!sLhW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>A harder request earns a different tool only when that tool can resolve the remaining uncertainty.</em></p><div><hr></div><p>A difficult support request can need a database lookup, a classifier, and a person without ever needing a frontier model. The mistake is treating difficulty as one quantity. Missing permission, unfamiliar wording, conflicting logs, and an exception request are different problems. Spending more inference on all four makes the workflow expensive while leaving some of them unresolved.</p><p>Consider a hypothetical customer message: &#8220;My export failed after the plan change. Please reset the limit and explain what happened.&#8221; The service must establish access, identify the responsible queue, retrieve evidence, explain the failure, and handle a requested account change. Each step needs its own output and acceptance condition. The decision ladder assigns those jobs to the smallest adequate primitive; it does not send every request through every rung.</p><p>Begin with the branch that admits no probabilistic override. Authenticated identity, current entitlement, exact quota arithmetic, and permitted operations come from trusted records and policy. Open Policy Agent illustrates the separation between <strong><a href="https://www.openpolicyagent.org/docs">evaluating policy against structured input and enforcing the resulting decision</a></strong>. In this design, the account service enforces the boundary. Missing or stale records trigger a refresh or a hold, never a model&#8217;s guess about what the customer deserves.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sLhW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sLhW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!sLhW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!sLhW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!sLhW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sLhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1826579,&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://signalovernoise.tech/i/218754876?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.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_!sLhW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!sLhW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!sLhW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!sLhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c52fd58-f60c-4b81-9ddc-80a53d110d67_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Rules have a small computational bill when the inputs are already available, although database reads and policy distribution still add latency. Their evidence is boundary tests, explicit treatment of missing fields, and review by the policy owner. Their maintenance burden is keeping definitions and records synchronized. The characteristic failure is an obsolete or incomplete rule that produces a perfectly repeatable wrong answer. Determinism makes behavior inspectable; it does not make policy correct.</p><p>Language begins at the next branch. If the only job is finding a documented error identifier, a lexical matcher may suffice. Keep a quoted identifier from the customer distinct from the same identifier in a trusted log. If the job is assigning varied descriptions to stable queues, compare a supervised text classifier with that simple baseline. Scikit-learn documents <strong><a href="https://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction">TF-IDF text features</a></strong> and <strong><a href="https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression">logistic regression classification</a></strong>, an ordinary combination worth testing before adding a general model.</p><p>The classifier earns automatic routing with representative held-out tickets, per-queue error analysis, and unfamiliar-topic cases. A compact local classifier can avoid a hosted round trip, but labeling, retraining, and changing vocabulary are recurring costs. An unseen category may still receive a familiar label. Give unsupported inputs a review path, and test the threshold for accepting a route rather than assuming the highest score is adequate. The router selects an owner; it does not diagnose the export.</p><p>Evidence retrieval is a separate job. Embeddings can find incident notes whose wording differs from the ticket, while a cross-encoder can score the query and each candidate together. Sentence Transformers documents this <strong><a href="https://www.sbert.net/examples/sentence_transformer/applications/retrieve_rerank/README.html">retrieve-and-rerank arrangement</a></strong>: broad retrieval narrows the set before more expensive pair scoring. Indexed embeddings shift some work to document ingestion; reranking adds work per candidate. Neither component creates a missing log or establishes that a similar incident caused this failure.</p><p>Measure retrieval against known relevant documents and realistic near misses. Maintain the index when documentation, access controls, or embedding models change; filter evidence to the authenticated account&#8217;s permitted scope. A reranker cannot recover a document the retriever omitted. In the example, an incident about a different plan might rank highly while being inapplicable. Check product version, timestamps, and observed failure conditions before passing a passage to the next stage.</p><p>A specialized decision model belongs where the remaining output is bounded but its meaning requires language. Jev could select technical support, billing, or manual triage from defined criteria, or judge whether the message requests an exception. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/primitives">Choice, Score, and Noul primitives</a></strong> return option distributions, positions on described levels, and yes probabilities. Independent questions share state; application code combines the results. This is an alternative to the classifier when the decision contract benefits from language-defined criteria, not a mandatory call after classification.</p><p>Its acceptance evidence is a labeled workload, threshold and abstention analysis, and tests of misleading wording. Maintenance includes the question definitions and model version: TypeSafe currently maps its aliases to <strong><a href="https://docs.typesafe.ai/models">Jev 1.13, with version pinning available</a></strong>. Hosted requests add network, timeout, and retry costs; a smaller output contract does not establish an end-to-end speed win. The vendor&#8217;s <strong><a href="https://docs.typesafe.ai/model-jaggedness/jev-1.13">jaggedness guide</a></strong> documents numeric and date weaknesses and susceptibility to adversarial state. Keep quota arithmetic and authorization outside the judge, even when its answer looks decisive.</p><p>Generation enters when the service needs a new explanation. A small generative model can draft a response from the verified export event, applicable documentation, and proposed next step. An enumerated route can also accompany that draft when combining the jobs proves simpler. OpenAI&#8217;s <strong><a href="https://developers.openai.com/api/docs/guides/structured-outputs">Structured Outputs documentation</a></strong> distinguishes schema constraints from ordinary JSON validity and warns that structured responses can still contain mistakes. A valid field containing an invented cause fails the task.</p><p>Test the small model on factual support, complete qualifications, refusal to invent absent evidence, and response usefulness. Its cost depends on input and output length, concurrency, and whether serving is local or hosted. Maintaining it means preserving prompts, model revisions, retrieval contracts, and semantic checks alongside schema validation. The common failure is an explanation that sounds finished before the investigation is finished. The customer reply stays a draft until those checks pass.</p><p>Frontier reasoning earns the next branch only when additional interpretation could settle the case. Conflicting logs or several plausible mechanisms may justify a stronger model proposing diagnostics. Compare accepted resolutions against the small-model baseline, including fabricated explanations and unnecessary tool proposals. Budget the complete attempt, including reasoning, retrieval, retries, and human correction; there is no universal latency ranking implied here. More capability brings another prompt, version, and tool-contract surface to maintain. If the necessary event record does not exist, fetch it or stop instead of buying a longer speculation.</p><p>Human review can enter from any branch. In this example, a requested limit reset outside ordinary entitlement goes directly to an authorized account owner, even if every model agrees. Send the original request, relevant records, proposed change, policy boundary, and unresolved question in one evidence packet. Give the queue a response deadline, a backup owner, and an appeal path. Human capacity has a labor bill and a waiting-time distribution; overload and inconsistent decisions are failure modes worth measuring, not proof that the queue should be automated away.</p><p>The concrete flow is therefore access check, accepted route, permitted evidence retrieval, checked explanation, and separately authorized action. A known error can use a maintained reply template and skip generation. An unsupported topic goes to triage; insufficient logs trigger an evidence request; a policy exception goes to its owner. A timeout preserves the ticket and holds protected changes. The account service rechecks mutable state immediately before applying an approved operation, then records the result.</p><p>Thresholds connect the components without pretending their scores mean the same thing. A retrieval score, classifier probability, and Jev distribution cannot share one generic confidence cutoff. Scikit-learn&#8217;s <strong><a href="https://scikit-learn.org/stable/modules/calibration.html">calibration guide</a></strong> describes comparing predicted probabilities with observed frequencies. Choose acceptance boundaries on separate validation cases, accounting for error costs and reviewer capacity, then report performance on a held-out set. Until that evidence exists, semantic routes remain proposals. No threshold in this reference architecture has been measured here.</p><p>There is a credible objection: a low-volume service may be easier to own with one constrained generative call than with several specialized dependencies. The ladder allows that outcome. Compare total cost per accepted ticket, elapsed time including review, missed costly errors, and the work of maintaining the route. Evaluate the simplest credible baseline first. Replace it only where another primitive handles a documented failure or reduces the complete operating bill without weakening containment.</p><p>Take one actual workflow and write down the next decision, its allowed outputs, trusted evidence, expensive mistake, and owner when it cannot proceed. Start with the lowest rung that can meet those requirements, then keep the cases where it fails. Those cases tell you whether to improve the evidence, change the primitive, or hand the decision to someone with authority. The next model call should have a job description before it has a budget.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Jev Is Not New Technology. Its Software Contract Might Be.]]></title><description><![CDATA[The useful novelty is a decision that becomes easier to own, not a new history of machine learning.]]></description><link>https://signalovernoise.tech/p/jev-is-not-new-technology-its-software</link><guid isPermaLink="false">https://signalovernoise.tech/p/jev-is-not-new-technology-its-software</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Sat, 03 Oct 2026 10:55:07 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rBOp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The useful novelty is a decision that becomes easier to own, not a new history of machine learning.</em></p><div><hr></div><p>Jev does not have to invent classification to make classification easier to use. The skeptical response to its launch has a sound premise: machines have returned labels, scores, and probabilities for decades. Calling those outputs a new kind of intelligence does not erase that history. The useful question is whether the interface changes the work of building and maintaining a decision system.</p><p>Start with the older contract. A conventional classifier learns a relationship between features and labeled outcomes, then predicts within its fitted class set. Scikit-learn&#8217;s <strong><a href="https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression">logistic regression documentation</a></strong> describes a classification model with predicted probabilities, including binary and multinomial cases. A program can consume those values, compare them with thresholds, and choose a route. Typed numbers that drive software are familiar machinery, not a September 2026 invention.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rBOp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rBOp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!rBOp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!rBOp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!rBOp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rBOp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2210799,&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://signalovernoise.tech/i/218626853?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.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_!rBOp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!rBOp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!rBOp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!rBOp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09aa8803-a7eb-4193-aeac-0305ef5a9785_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>That machinery remains a serious competitor. Suppose a hypothetical issue-intake service assigns reports to defect, documentation, feature request, or manual review. If those labels are stable and representative examples exist, a supervised classifier deserves a test. Its training data, feature pipeline, fitted artifact, and operating threshold give the team concrete things to inspect. A new hosted endpoint has to beat that arrangement on the actual workload, including the cost of keeping it correct.</p><p>Natural-language labels are not new either. Yin, Hay, and Roth&#8217;s <strong><a href="https://aclanthology.org/D19-1404/">2019 zero-shot text classification paper</a></strong> studied an entailment formulation across topics, emotions, and situations, including evaluation with fully unseen labels. That is a direct predecessor to the idea of describing a category rather than collecting task-specific examples for every category. It does not prove equivalence to Jev&#8217;s training or performance. It does remove the claim that classification with language-defined targets arrived with this launch.</p><p>The existing implementation is accessible enough to belong in the comparison. Hugging Face&#8217;s <strong><a href="https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.ZeroShotClassificationPipeline">zero-shot classification pipeline</a></strong> accepts candidate labels at runtime, pairs text with hypotheses, and uses an entailment model to score them. Its single-label and multi-label modes normalize scores differently. That last detail matters: a probability-shaped value inherits the meaning of the process that produced it. Matching field types across two APIs does not make their scores interchangeable.</p><p>Jev offers a more explicit programming surface around bounded judgment. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/primitives">primitives contract</a></strong> takes shared state and named questions, with criteria supplied in the request. Choice returns a distribution over options, Score evaluates ordered descriptive levels, and Noul returns a yes probability. Independent questions see the same state; code combines their answers. The appeal is a reusable interface for several decision shapes, rather than a separate prompt-and-parser design for each one.</p><p>The maintenance distinction is worth isolating. In the issue-intake example, a new product area can bring a new routing definition, while severity and whether the report describes a regression remain separate judgments. With Jev, the application can express those definitions in questions and criteria without training a customer-specific model. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/models">model documentation</a></strong> says the same weights serve every account and domain adaptation happens through the request. That moves some work from fitting an artifact to defining and testing a contract. It does not eliminate the work.</p><p>A hand-written rule can have a smaller maintenance bill still. If a trusted field says the issue belongs to a retired project, the application can place it in that project&#8217;s archive queue without consulting any semantic model. Exact identifiers, date ordering, and permission boundaries should keep their ordinary implementations. A decision API is useful where language creates uncertainty. Putting a rule behind an inference call makes a known answer depend on service availability and model behavior.</p><p>The generative alternative also deserves a fair comparison. &#8220;Return JSON&#8221; is weaker than a defined schema: OpenAI&#8217;s <strong><a href="https://developers.openai.com/api/docs/guides/structured-outputs">Structured Outputs guide</a></strong> distinguishes JSON mode, which targets valid JSON, from Structured Outputs, which constrains supported schemas. An enumerated route can therefore be a typed result from a generative model too. Jev cannot claim exclusive ownership of machine-readable answers. Its narrower contract gives up generated explanations and open-ended synthesis, which may help a bounded step but may require another component elsewhere.</p><p>That tradeoff is visible when issue intake needs both a category and a useful explanation for a maintainer. One generative call can propose both. A specialized judge can supply the category while another stage drafts the explanation from verified evidence. The split is worthwhile only if the complete route wins: accepted classification, explanation quality, elapsed time, retries, and review effort. There is no systems prize for replacing one dependable call with two dependencies because the second diagram looks more disciplined.</p><p>The strongest criticism, then, is that a team could build a similar interface around existing classifiers or constrained generation. I agree. A map of questions and typed answers is an API design, not evidence of a unique mathematical breakthrough. Product value can still come from maintaining that interface, supporting its decision shapes, and reducing how much glue each application owns. Whether TypeSafe delivers that value is an empirical question. A plausible contract earns a comparison, not an exemption from one.</p><p>Even the convenience of editing criteria has a hidden cost. Change &#8220;defect&#8221; from broken documented behavior to any disappointing behavior, and old labels may no longer describe the task. Adding a new option changes the decision space; renaming one can change its interpretation. Version the question definitions beside the model and evaluation set. A request that still validates can be making a different decision from the one you approved last week.</p><p>Probability adds another contract to maintain. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/confidence">confidence documentation</a></strong> defines Choice and Score confidence from the concentration of their distributions; Noul has no separate confidence field. Scikit-learn&#8217;s <strong><a href="https://scikit-learn.org/stable/modules/calibration.html">calibration guide</a></strong> explains the different requirement that predicted probabilities agree with observed frequencies. A clean response can be confidently wrong. The issue-intake service needs to measure missed defects separately from needless escalations, then give ambiguous reports a queue with an owner rather than force a label.</p><p>The current failure documentation makes that test more concrete. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/model-jaggedness/jev-1.13">Jev 1.13 jaggedness page</a></strong>, reviewed October 2, lists literal interpretation, numeric and date weaknesses, distracting state, adversarial content, and Choice option-order effects. Test reordered options, contradictory definitions, and reports that insist on their own classification. Compute dates and counts in code. A model&#8217;s neat probability vector should not be allowed to turn an issue&#8217;s self-description into authority over the workflow.</p><p>I would evaluate this as a maintenance experiment as much as a model experiment. Freeze one labeled intake set with ambiguous cases and expensive errors. Compare an exact-rule baseline, a supervised classifier when the data supports it, an entailment-based zero-shot model, constrained generation, and Jev. Then change one realistic routing definition and measure the work required to recover acceptable behavior. Keep accuracy by class, accepted coverage, reviewer load, total cost, latency, and failure handling in the same record. None of those results has been measured for this hypothetical service here.</p><p>The adoption decision belongs at that level. A stable classifier may win by leaving little to maintain. A changing semantic workflow may benefit from criteria that travel with the request. A general model may remain the better choice when explanation and classification cannot usefully be separated. Jev&#8217;s contract matters if it makes a changing decision cheaper to own while preserving a dependable place to stop. The history of machine learning can stay intact while the software interface earns its keep.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Jev Does Not Generate Text. That Is the Point.]]></title><description><![CDATA[The launch brings bounded judgment into application code.]]></description><link>https://signalovernoise.tech/p/jev-does-not-generate-text-that-is</link><guid isPermaLink="false">https://signalovernoise.tech/p/jev-does-not-generate-text-that-is</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Fri, 02 Oct 2026 09:07:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!G4pR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The launch brings bounded judgment into application code. The acceptance test still belongs to the builder.</em></p><div><hr></div><p>A decision endpoint can be useful precisely because it cannot write you a convincing explanation. Jev gives software a bounded answer and a probability instead of a paragraph to interpret. That restriction is the story. The September launch put a different contract within reach of application code: define the judgments, supply the evidence, and keep the resulting behavior in the program.</p><p>TypeSafe announced Jev in early access on September 15. Its <strong><a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev">launch account</a></strong> describes a model stack trained for calibrated decisions, with parallel outputs rather than sequential text generation. Those are the company&#8217;s architectural and training claims. The observable interface is narrower: you ask questions with defined answer spaces. You do not ask it to write a migration plan, explain a diagnosis, or invent the next tool argument.</p><p>The uptake gives that interface a reason to be examined now. In its September 18 <strong><a href="https://vercel.com/blog/ai-gateway-jev-model-launch">AI Gateway launch report</a></strong>, Vercel said nearly 13 percent of its paid Gateway teams used Jev within the first 24 hours. It reported more than twice the first-day team adoption of any previous model launch there. That denominator matters. This is Vercel&#8217;s account of activity inside one paid gateway population, with no evidence here of market share, retained usage, or successful automation. Trying an endpoint and trusting its decisions are different milestones.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G4pR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G4pR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!G4pR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!G4pR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!G4pR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G4pR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1974822,&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://signalovernoise.tech/i/218470781?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.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_!G4pR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!G4pR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!G4pR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!G4pR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45441f05-a60a-401a-a8ed-15c7414d61c1_1672x941.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 released framework support is more concrete than a popularity chart. <strong><a href="https://github.com/stanfordnlp/dspy/releases/tag/3.4.0">DSPy 3.4.0</a></strong>, published September 25, adds an optional TypeSafe backend and experimental Noul, Choice, and Score fields to ordinary signatures. Its predictor translates the inputs and field criteria into decision requests. The release also adds ReAnchor for fitting decision thresholds, rubric cuts, and option weights against a program metric. This is an implementation that builders can inspect, not proof that any particular workflow has improved.</p><p>The direct <strong><a href="https://docs.typesafe.ai/api">TypeSafe API</a></strong> accepts one shared state and a map of typed questions. State can be a string, JSON object, or array of text values. Each question includes instructions; its criteria define the options or rubric where needed. Independent questions run against the same evidence. An answer from one question does not secretly become evidence for another. If the next question requires a record selected by the first answer, code must fetch that record and make another request.</p><p>The <strong><a href="https://docs.typesafe.ai/primitives">three primitives</a></strong> describe three different jobs. Choice returns a selected option and a distribution over the supplied alternatives. Noul returns the probability that a condition holds, without a separate confidence field. Score returns a probability-weighted position across ordered, described levels. A Noul near one-half signals uncertainty about yes or no; it does not describe a condition as half present. A Score is a judgment against a rubric, not a replacement for arithmetic.</p><p>Consider a hypothetical release-note intake service. It already knows which repositories it follows and which version tags it has processed. Code handles those exact checks. The remaining work is semantic: choose the destination among a few maintained indexes, judge whether the text describes a breaking interface change, and rate migration effort against concrete levels. Those questions can share the release note and relevant definitions. A generative model can later draft an explanation from the verified material, after the intake decisions have been checked.</p><p>The candidate set is part of the design. Include an unsupported destination when the known indexes do not cover the note. Keep source dates and version ordering in code. An uncertain breaking-change judgment can queue the note for a maintainer, while an unavailable decision service leaves the item pending. No probability should let the intake service alter a deployment. Even this modest workflow needs an owner for the cases it cannot settle, or its uncertainty path becomes a pile of forgotten notes.</p><p>That boundary also makes the current operating limits easier to understand. The <strong><a href="https://docs.typesafe.ai/models">model documentation</a></strong> lists Jev 1.13 as jev-1.13.0; both jev-latest and jev-preview currently resolve to it. Direct pricing is $0.042 per million input tokens, with output tokens free. The request budget is 64,000 tokens overall, with a separate 32,000-token limit for state plus the longest question. Input is text only. The same page warns that rate limits can change. Pin the version when evaluating thresholds, and record the returned model ID.</p><p>The integration route needs equal care. Vercel&#8217;s <strong><a href="https://vercel.com/docs/ai-gateway/modalities/evaluation">evaluation documentation</a></strong> exposes typesafe-ai/jev through AI SDK 7&#8217;s experimental evaluation API and an HTTP evaluation endpoint. It explicitly excludes the OpenAI-compatible chat endpoint. A <strong><a href="https://vercel.com/docs/ai-gateway/sdks-and-apis/typesafe">TypeSafe-compatible Gateway route</a></strong> also exists for existing clients. That is a transport choice with its own credentials and billing, not permission to treat every interface&#8217;s field names, context limits, and prices as interchangeable. The direct model contract is the baseline quoted above.</p><p>TypeSafe&#8217;s performance pitch deserves a narrower reading than its headline. The launch post attributes its 193.6-times speed and 444.6-times cost figures to its own workflow evaluations and says these likely sit toward the high end of real-world gains. It also discloses that the workflow references use other models&#8217; probabilities, rather than ground-truth classification labels. The results are vendor-reported. They justify an experiment on a decision-shaped workload; they do not establish those gains for a release-note service, a different network location, or a simpler classifier baseline (<strong><a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev">methodology and caveats</a></strong>).</p><p>The strongest alternative remains keeping a bounded output inside the generative model already in the application. Structured output can give that model an enumerated answer too. If the workflow needs an explanation and a label from the same evidence, a separate hosted judge adds a dependency, a timeout, and another evaluation surface. Jev has to earn the split through accepted decisions at lower total cost or latency. Removing prose from one response is a clean interface improvement, not an automatic systems improvement.</p><p>There is also no semantic guarantee hiding inside type safety. The label can belong to the allowed set and still be wrong. TypeSafe&#8217;s <strong><a href="https://docs.typesafe.ai/model-jaggedness/jev-1.13">Jev 1.13 jaggedness guide</a></strong>, last reviewed September 17, documents literal interpretation, weak numeric precision, unreliable date comparisons, distracting state, and susceptibility to adversarial content. These are practical acceptance cases. Feed the intake judge a note that argues it is harmless while describing a removed API. Test a missing prerequisite and a contradictory rubric. Keep counting and version comparisons outside the model.</p><p>Confidence does not repair those failures by itself. TypeSafe derives <strong><a href="https://docs.typesafe.ai/confidence">Choice and Score confidence from their probability distributions</a></strong>. It describes how concentrated the answer is, rather than measuring your workflow&#8217;s correctness. DSPy&#8217;s Noul confidence has another meaning: distance from the configured threshold. Neither field establishes calibration on your release notes. Keep their definitions separate in the evaluation record, and compare predicted probabilities with observed outcomes before turning them into operating policy.</p><p>I would begin with a shadow test that changes no routing visible to users. Freeze a representative labeled set, including vague notes, unfamiliar components, missing information, and misleading wording. Compare Jev with the existing route and a simple baseline. Measure missed breaking changes separately from needless escalations. Record total elapsed time and cost per accepted decision, including retries and maintainer review. A faster answer that misses the expensive failure has lost the comparison.</p><p>Only promote the cases that earn it. Preserve the original evidence, question definitions, probabilities, version, chosen route, and eventual outcome. Send uncertain inputs to someone who owns the queue; retain them when the service fails. Refresh mutable facts before an action follows. The launch makes bounded judgment easier to buy and compose. The application still has to decide which judgments deserve consequences.</p><p>Jev does not need to become the model that handles the whole request. It needs to win one decision your software currently pays a generative model to make. Give it a small answer space, a real acceptance test, and a safe place to stop. The useful adoption number is how many decisions survive that test.</p><div><hr></div><p>Subscribe to <strong><a href="https://signalovernoise.tech/">Signal Over Noise</a></strong> for practical analysis of AI agents and automation: what to test, which constraints matter, and when a tool is worth using. Bring the next idea to one bounded workflow and check the result before expanding it.</p><p><em>If this was useful, forward it to one engineer who needs less noise in their feed.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/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://signalovernoise.tech/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share Signal Over Noise&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://signalovernoise.tech/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share Signal Over Noise</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The LLM Should Not Make Every Decision]]></title><description><![CDATA[Choose the primitive by the job, and give uncertainty somewhere accountable to go.]]></description><link>https://signalovernoise.tech/p/the-llm-should-not-make-every-decision</link><guid isPermaLink="false">https://signalovernoise.tech/p/the-llm-should-not-make-every-decision</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Thu, 01 Oct 2026 08:55:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!U6SP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69d64f7f-44f2-475f-b668-80c5a23ba223_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Choose the primitive by the job, and give uncertainty somewhere accountable to go.</em></p>
      <p>
          <a href="https://signalovernoise.tech/p/the-llm-should-not-make-every-decision">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[What September 2026 Taught Us About Bigger Models on Smaller Boxes]]></title><description><![CDATA[The useful limit is accepted work within a budget, not the largest checkpoint that starts.]]></description><link>https://signalovernoise.tech/p/what-september-2026-taught-us-about</link><guid isPermaLink="false">https://signalovernoise.tech/p/what-september-2026-taught-us-about</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Wed, 30 Sep 2026 09:35:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0gU1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99c6e17f-26dc-4d61-9488-6b3d537ec1e9_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The useful limit is accepted work within a budget, not the largest checkpoint that starts.</em></p>
      <p>
          <a href="https://signalovernoise.tech/p/what-september-2026-taught-us-about">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[A Realistic Local Video Workstation with a 5080 and a 3090]]></title><description><![CDATA[Two mismatched cards work best as a production line, not a shared bucket of VRAM.]]></description><link>https://signalovernoise.tech/p/a-realistic-local-video-workstation</link><guid isPermaLink="false">https://signalovernoise.tech/p/a-realistic-local-video-workstation</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Tue, 29 Sep 2026 10:51:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5Vey!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96cf28e0-5ade-4df7-b023-d7d2221d21c3_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Two mismatched cards work best as a production line, not a shared bucket of VRAM.</em></p>
      <p>
          <a href="https://signalovernoise.tech/p/a-realistic-local-video-workstation">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[ComfyUI-MultiGPU: Use the Second Card as a Donor, Not a Magic Pool]]></title><description><![CDATA[The useful design assigns each device a job and measures every transfer between them.]]></description><link>https://signalovernoise.tech/p/comfyui-multigpu-use-the-second-card</link><guid isPermaLink="false">https://signalovernoise.tech/p/comfyui-multigpu-use-the-second-card</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Mon, 28 Sep 2026 09:41:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!VNRV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F576e4c5d-3b80-4822-b148-37e5c75f88bb_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The useful design assigns each device a job and measures every transfer between them.</em></p>
      <p>
          <a href="https://signalovernoise.tech/p/comfyui-multigpu-use-the-second-card">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Eight Gigabytes Is Not Dead for Local Image Generation]]></title><description><![CDATA[The right model and workflow beat a larger checkpoint that spends every iteration crossing PCIe.]]></description><link>https://signalovernoise.tech/p/eight-gigabytes-is-not-dead-for-local</link><guid isPermaLink="false">https://signalovernoise.tech/p/eight-gigabytes-is-not-dead-for-local</guid><dc:creator><![CDATA[Justin Wilson]]></dc:creator><pubDate>Sun, 27 Sep 2026 10:10:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GHan!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc740121b-4f66-4200-894a-3c5d1852e192_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The right model and workflow beat a larger checkpoint that spends every iteration crossing PCIe.</em></p>
      <p>
          <a href="https://signalovernoise.tech/p/eight-gigabytes-is-not-dead-for-local">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>