<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Guillermo Baigorria on Medium]]></title>
        <description><![CDATA[Stories by Guillermo Baigorria on Medium]]></description>
        <link>https://medium.com/@baigorria?source=rss-c4d55ae2e0bc------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*GkF34FEeJivG13Id</url>
            <title>Stories by Guillermo Baigorria on Medium</title>
            <link>https://medium.com/@baigorria?source=rss-c4d55ae2e0bc------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 00:59:37 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@baigorria/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How we fix an AI agent’s mistakes: data first, prompt last]]></title>
            <link>https://medium.com/@baigorria/how-we-fix-an-ai-agents-mistakes-data-first-prompt-last-16b1d17a566b?source=rss-c4d55ae2e0bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/16b1d17a566b</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Guillermo Baigorria]]></dc:creator>
            <pubDate>Sun, 08 Nov 2026 17:00:57 GMT</pubDate>
            <atom:updated>2026-11-10T14:26:26.689Z</atom:updated>
            <content:encoded><![CDATA[<h4>A wrong card is rarely a prompt problem, so read what the model received before you touch a word.</h4><figure><img alt="A boy and a cybernetic robot dog weave through a line of striped test poles in a ranch paddock at sunset." src="https://cdn-images-1.medium.com/max/1024/1*VrqH8PE2RPNRYOyoCE1dqQ.jpeg" /><figcaption>Image created with AI.</figcaption></figure><p>For years, one way to teach a model the cases of a product was fine-tuning: training it on your own examples. That road is closing. According to its <a href="https://developers.openai.com/docs/deprecations">deprecations page</a>, since May 2026 OpenAI no longer lets organizations that have never fine-tuned create new training jobs, and from January 2027 its existing customers won’t be able to either.</p><p>If the model is rented, as we argued in the <a href="https://medium.com/@baigorria/rent-the-model-own-the-harness-how-to-build-a-model-agnostic-ai-agent-7c921a888e61">first post</a>, then what has to learn from mistakes is the harness. Here is how we do it: every reply can be reported; a mistake is fixed in the data first, then in the missing fact, and only then in the prompt; and each fix is proven by a family of test cases that run more than once. This is the last post in the series.</p><h3>Make every mistake reportable on the spot</h3><p>Back to the note from the <a href="https://medium.com/@baigorria/one-voice-note-three-requests-how-we-built-an-llm-router-599dfcbb3b54">second post</a>. The project has two open Novak jobs, the panel installation and a battery quote, and suppose this time Werk gets it wrong: it marks the quote as done. The person replies “it was the installation,” and Werk undoes the change and makes it on the right card. For them, the problem ends there.</p><p>For the harness, that’s where the work starts. A mistake that only gets fixed in the chat will happen again with the next client who has two open jobs. That’s why every reply from Werk can be reported: pick a reason and, if you like, add a voice note or a few words explaining it.</p><p>It pays to have this from day one, when it still seems early, and to decide who reads the reports. What someone writes in a report is part of their team’s work. At Werk, an agent reads those reports, not a person.</p><h3>Data first, instructions last</h3><p>Faced with a model’s mistake, the temptation is to go straight to the prompt and add a line. First, read everything the model received on that turn, in full: not what the code was supposed to send, but the exact request that went out to the provider, with the instructions, the conversation, the cards and the message. Then the questions come in order.</p><p>The first is whether the data was right. If the conversation arrived incomplete, the right card wasn’t among the candidates, or two parts of the context contradicted each other, the model had no way to get it right, and the fix belongs in the harness. In the Novak case, the data was right: the model saw both cards and where each one matched.</p><p>The second is whether a fact was missing. The model lacked what the person knew by heart: the installation was theirs and they had started it that morning, while the quote belonged to someone else. No instruction can replace a fact the model can’t see. The fix is to show it who holds each card and what state it’s in.</p><p>Only after those two questions do you look at the instructions, when the model has correct, complete data and still gets it wrong. Even then, what you write is a principle, never a rule for the case. A line like “if they say Novak, it’s the installation” fixes this note and breaks next week’s, when the quote is the one that’s done.</p><h3>From one mistake to a family of cases</h3><p>A fix has to be proven, and one case won’t prove it. The Novak report gives you a class of mistake: two open jobs for the same client, and a message that doesn’t say which.</p><blockquote>No instruction can replace a fact the model can’t see.</blockquote><p>From that class you write a family of cases: the same situation in other words and other languages, as a voice note, with two different clients who share a name. And the opposite case too, with a single open job, where there’s nothing to be unsure about. If the fix only works for “done with the Novak job,” the mistake is still there.</p><figure><img alt="Diagram: a report becomes a class of mistake and a family of cases, gets fixed in the data, the missing fact or the instructions, and is checked by the battery before going back to daily use." src="https://cdn-images-1.medium.com/max/1024/0*q2zCxL8fME5aQKuG.png" /></figure><p>These cases are best written by someone other than whoever makes the fix. Whoever fixes something tends to test exactly what they fixed; whoever starts from the class of mistake tests what the person needs. That way special cases live in the test battery, not in the prompt: the instructions state principles, and the cases check that those principles hold.</p><h3>Measure more than once</h3><p>A model doesn’t always answer the same message the same way. <a href="https://arxiv.org/abs/2406.12045">τ-bench</a> (2024), a benchmark of agents that serve customers with tools, measured it: even the best agents of the time solved fewer than half of the tasks. And in its retail setting, the chance of solving the same task correctly on all eight tries fell below 25%.</p><p>That’s why every case runs more than once. A fix that passes once and fails on the next run isn’t done.</p><p>A case that fails one time in ten is a mistake someone will run into on a roof, sooner or later.</p><blockquote>The chance of solving the same task correctly on all eight tries fell below 25%. (τ-bench, 2024)</blockquote><p>And when a fix goes in, run the whole battery, not just the new cases. That’s how you know a mistake was fixed without breaking something else.</p><h3>The harness learns with use</h3><p>Models will keep getting things wrong now and then, like anyone working in a hurry. What you can build is what happens next: every reported mistake becomes a family of cases, and those cases get checked every time something changes.</p><p>Developers and office workers already have a harness built for their work. The person installing solar panels on a roof now has one too, and every mistake someone reports makes it better for everyone.</p><p><em>Originally published at </em><a href="https://blog.getwerk.ai/posts/how-to-test-a-harness-that-learns-from-its-mistakes"><em>https://blog.getwerk.ai</em></a><em> on November 8, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=16b1d17a566b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[One voice note, three requests: how we built an LLM router]]></title>
            <link>https://medium.com/@baigorria/one-voice-note-three-requests-how-we-built-an-llm-router-599dfcbb3b54?source=rss-c4d55ae2e0bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/599dfcbb3b54</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <dc:creator><![CDATA[Guillermo Baigorria]]></dc:creator>
            <pubDate>Tue, 03 Nov 2026 20:26:52 GMT</pubDate>
            <atom:updated>2026-11-10T14:08:45.606Z</atom:updated>
            <content:encoded><![CDATA[<h4>Done with the Novak job, start the school job at 9, remind me at 8: how one hurried voice note becomes three pieces of work.</h4><figure><img alt="Illustration of a boy in a fenced field at sunset pointing up while a friendly white robot dog in an orange harness rises on its hind legs" src="https://cdn-images-1.medium.com/max/1024/1*lnFeksOFZkTgJ2ILYejmlQ.jpeg" /><figcaption>Image created with AI.</figcaption></figure><p>In the <a href="https://medium.com/@baigorria/rent-the-model-own-the-harness-how-to-build-a-model-agnostic-ai-agent-7c921a888e61">first post</a> of this series, a four-second voice note helped us separate what the model does from what the harness does: “Done with the Novak job.” That was the easy case. A real day sounds more like this: “Done with the Novak job. We’re starting the school job tomorrow at 9, remind me at 8.”</p><p>That one voice note holds three requests: close a job, record a new one and set a reminder. Whoever records it on the way down from the roof won’t send them one at a time or say which card they mean, and they shouldn’t have to. This post shows how we built the harness so they don’t, in three decisions: a router that splits the message into requests and hands each to the agent that owns it, code that searches the project while the model chooses the card, and asking only when in doubt, never to confirm.</p><h3>A router that hands out work and decides nothing</h3><p>The router is the first thing every message touches, and it should do exactly one thing: split the message into requests and hand each one to the agent that owns that kind of work. In the Novak note, each of the three requests lands with a different agent, and each agent gets only its own.</p><p>The router splits a message by the things asked, not by sentences. “We’re starting the school job tomorrow at 9, remind me at 8” is one sentence and two requests: a new job with its start time, and a reminder. Each request travels with the person’s exact words rather than the router’s summary, so the agent reads what was actually said.</p><figure><img alt="Diagram: the router splits the voice note into three requests and gives each agent the exact words and the same context." src="https://cdn-images-1.medium.com/max/1024/1*Q7HKKp_kbA9t00Cz-uKGOw.png" /></figure><p>Everything else stays out of the router. It records nothing, picks no cards, looks for no keywords and has no rules for any language: it understands a request in whatever language it comes in. If it picked cards too, two pieces would be making the same decision, and sooner or later they would make it differently.</p><p>What the router knows about each agent isn’t written in the router either. It comes from what each agent declares about the work it does. Adding an agent, or changing what one does, never means touching the router.</p><h3>Show the model what the person saw</h3><p>To make sense of “the Novak job” or “tomorrow at 9,” the model needs what the person had in front of them when they recorded the note: the conversation as it looked on their screen. Every line carries its time, and the current time appears once, at the top. That way “tomorrow” means the same day to the router and to every agent.</p><p>Code searches and the model chooses. For “the Novak job,” code looks through everything a card holds, not just its title: the description, the notes, the text in its photos and what was said in its voice notes. It searches by words and by meaning, then hands the model a few candidates, each with the place where it matched: “Novak, in the title” or “Novak, in Tuesday’s voice note.”</p><p>With that, the model does what it does best: read the person’s words and decide which of those cards they mean. Showing it the whole project would make it slower, more expensive and easier to confuse. Showing it a single card would mean deciding for it.</p><p>There is one search per message, and both the router and the agent see its result. If each ran its own search, they could end up talking about different cards without knowing it.</p><blockquote><em>The router splits a message by the things asked, not by sentences.</em></blockquote><p>The model never handles a card’s internal ID, either. It sees each card by a short number, like #12, and code translates that number back into the real card. A long ID is easy to copy wrong; a short number isn’t.</p><h3>Ask only when in doubt, never to confirm</h3><p>The last decision is the one people notice most: when to ask. Werk doesn’t ask for confirmation. It does what it’s asked and says what it did. If something wasn’t right, it can be undone from the same chat, and each card’s history keeps every change.</p><p>Asking “Confirm?” before every change looks careful, but with use it stops being careful. Anthropic describes this in its post on <a href="https://www.anthropic.com/engineering/claude-code-auto-mode">how it built auto mode for Claude Code</a> (2026): when people have to approve so many actions, they stop looking at what they approve. In practice, users accept 93% of permission prompts anyway.</p><p>For someone working on a roof, every confirmation is also an interruption: phone out again, gloves off again. So Werk asks only when it truly can’t tell. If the project has two open Novak jobs, the panel installation and a battery quote, “done with the Novak job” fits both. If nothing else tells them apart, Werk asks which one instead of guessing.</p><p>The two questions look alike, but they aren’t. “Which one?” asks the person for a fact the harness doesn’t have. “Confirm?” asks for permission they already gave when they sent the message.</p><blockquote><em>In practice, users accept 93% of permission prompts anyway. (Anthropic, 2026)</em></blockquote><p>Even so, the harness will sometimes get it wrong. How that mistake gets caught, how it becomes a test and where it gets fixed is the subject of the third post.</p><p>That way, people on the move can keep talking the way they do, in a hurry and with three things in one breath, and each one ends up where it belongs.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=599dfcbb3b54" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Prompt caching: same agent, same rules, about a quarter of the bill]]></title>
            <link>https://medium.com/@baigorria/prompt-caching-same-agent-same-rules-about-a-quarter-of-the-bill-22494c6803fa?source=rss-c4d55ae2e0bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/22494c6803fa</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Guillermo Baigorria]]></dc:creator>
            <pubDate>Fri, 30 Oct 2026 20:33:26 GMT</pubDate>
            <atom:updated>2026-10-30T20:33:26.764Z</atom:updated>
            <content:encoded><![CDATA[<h4>Our test agent’s prompt looked fine and read nothing from the cache. Four moves later, it read up to 94%.</h4><figure><img alt="A line rising from 0% to 94%: the share of a small recipe agent’s prompt read from the cache, before and after four moves." src="https://cdn-images-1.medium.com/max/1024/1*viFEsuePktfaxAIikTSgkA.png" /></figure><p>Prompt caching has been covered a lot. The big providers’ guides explain how it works, and many posts tell how a team’s hit rate jumped after one fix. We want to add a way to watch it happen: one agent’s prompt, drawn the same way at every step, with the measured number in each picture. Sometimes the same idea, shown another way, is what makes it click.</p><p>To show it, we built a small recipe agent based on what happened in our own agents: a prompt that looks fine, fixed in four moves, every version sent to a real model API. Same model, same rules, not a word changed: its prompts got 73% cheaper, and the whole test cost less than a cent. At the end we show a test that keeps them from coming undone, and what the same moves did in ours.</p><h3>How a prompt cache decides what you pay</h3><p>Every call to a model sends the whole request again: the tools, the instructions and the conversation. A prompt cache lets the provider keep the work it already did on the start of a request, and reuse it when the next request starts exactly the same way. In the guides from <a href="https://developers.openai.com/api/docs/guides/prompt-caching">OpenAI</a> and <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">Anthropic</a>, reading from the cache costs a tenth of the normal input price or less, and writing to it a quarter more.</p><p>The rule behind it is short: a prompt cache reuses everything up to the first thing that changes. That is the whole game: what never changes goes first, and what changes goes last.</p><h3>Four moves on a recipe agent</h3><p>Our test agent writes recipes. It has two tools, find_in_pantry and save_recipe, about a thousand words of rules, and a profile for each person. The app has two plans: Pro can save recipes, free cannot. Ana is on the Pro plan and vegetarian; Leo is on the free plan. During one evening, each of them sends three messages.</p><h4>A prompt that looks fine</h4><p>This is the prompt many agents start with. The date goes on top, so the agent knows what day it is. Ana’s details come next, so it can personalize. Her plan decides which tools she gets. And like many harnesses, it builds the whole prompt again before every call to the model.</p><figure><img alt="The recipe agent’s first prompt: tools for her plan, then the date, Ana’s details and the rules, then her message. 0% of the evening came from the cache." src="https://cdn-images-1.medium.com/max/1024/1*Tv-PD4iKSLi0W78lQ4-LdQ.png" /></figure><p>The cache was on, and nothing came back from it. Every message wrote its whole prompt into the cache and none read it back, so the evening cost more than it would have with no cache at all.</p><h4>Step 1: Move what changes on every message to the end</h4><p>The date changes every minute, and it sits near the top. Whatever comes after it is new work on every message, the thousand words of rules included. Both guides say the same: what changes on every request goes at the end. So the date moves into the user message.</p><figure><img alt="Step 1: the date moves from the instructions to the user message. 65% of the evening came from the cache." src="https://cdn-images-1.medium.com/max/1024/1*ogcupUvSKhubB_9jl1aJLg.png" /></figure><p>Each person’s later messages now read almost their whole prompt from the cache, and the evening went from 0% to 65%. Anything that changes on every message goes at the end.</p><blockquote><em>A prompt cache reuses everything up to the first thing that changes.</em></blockquote><p>And yet Leo’s first message still read nothing.</p><h4>Step 2: Keep personal details out of the shared part</h4><p>Ana’s details change with the person. With them in the instructions, nobody else can reuse Ana’s prompt. So they move into the user message, and the instructions become the same text for everyone.</p><figure><img alt="Step 2: Ana’s and Leo’s details move to the user message. Leo’s tool list is shorter. 64% of the evening came from the cache." src="https://cdn-images-1.medium.com/max/1024/1*VYakPUZq7hGN1X7IQfdWQQ.png" /></figure><p>The evening went down a little, to 64%, because Ana’s details now travel with each of her messages. And Leo still read nothing. What belongs to one person goes after what everyone shares, but that alone was not enough: something still differed, and it came before the instructions.</p><h4>Step 3: Give every plan the same tool list</h4><p>The tools come before the instructions, and Leo’s free plan gave him a shorter list. His request differed from Ana’s at its very first line, so it could not reuse anything she had left in the cache.</p><p>The fix is to send every plan the same list. The list only describes the tools; it does not decide what Leo may use. That is decided apart: OpenAI’s guide says to “restrict which tools are callable while keeping the supplied tools list stable”, and the code that runs the tools refuses anything his plan does not allow. Give everyone the same menu, and decide at the table what each one may order.</p><figure><img alt="Step 3: Leo gets the same tool list as Ana, although his plan can’t use save_recipe. 80% of the evening came from the cache." src="https://cdn-images-1.medium.com/max/1024/1*f5JBsKz7h7VGOSLNV9SEDw.png" /></figure><p>Leo’s first message now reused what Ana had left in the cache, and the evening reached 80%. The plan still decides what each person can do; it just stopped deciding what the prompt says.</p><h4>Step 4: Tool calls almost free: append, don’t rebuild</h4><p>To answer Ana, the agent first checks her pantry: the model asks for find_in_pantry, the agent runs it and calls the model again with the result. If that call only adds the tool call and its result at the end, everything before them comes from the cache. OpenAI&#39;s guide puts it plainly: &quot;Append new messages rather than rewriting earlier turns.&quot;</p><figure><img alt="Step 4: the call after the tool call adds two lines at the end of the request. 94% of it came from the cache." src="https://cdn-images-1.medium.com/max/1024/1*lONEhbxPSU_5rcfq0EB3EQ.png" /></figure><p>The call after the tool read 94% of its prompt from the cache. An agent makes many calls like this one, so they end up almost free. In the first version, the agent rebuilt the whole prompt before every call, with a fresh time on top, and the same call read nothing. A tool call should add to the request, never rebuild it.</p><h4>What the four moves add up to</h4><p>Together, the four moves changed what the evening cost. At a price of $1 per million input tokens, its prompts went from $1.76 to $0.48 per thousand calls, and the call after the tool cost $0.25.</p><figure><img alt="Results by step: 0%, 65%, 64% and 80% of the evening from the cache, and 94% for the call after a tool. Prompt cost per 1,000 calls from $1.76 to $0.48, and $0.25 after a tool call." src="https://cdn-images-1.medium.com/max/1024/1*HTiRoWI1f4YAfj3w30-IFQ.png" /></figure><p>None of the four moves changed a word of the rules. We ran the test on gpt-6-luna with reasoning off; for any model, multiply these costs by its price per million input tokens.</p><h3>Check your own agent</h3><p>Take two requests your agent sends, from two people a minute apart, and find the first place where they differ. Everything before it can come from the cache; everything after it is paid on every call. If that place is near the top, look at what sits there: a date, a name, a tool list built for one plan.</p><p>Then keep it that way with a test. This one never calls a model: it builds two requests and compares how they start.</p><pre># two people, two times: the start of their requests must be identical<br>ana = build_request(ANA, &quot;6:42 PM&quot;, &quot;What can I make tonight with chickpeas and spinach?&quot;)<br>leo = build_request(LEO, &quot;6:43 PM&quot;, &quot;A quick lunch with eggs for tomorrow?&quot;)<br>assert ana[&quot;tools&quot;] == leo[&quot;tools&quot;]                 # the same tool list<br>assert ana[&quot;messages&quot;][0] == leo[&quot;messages&quot;][0]     # the same instructions<br> <br># the call after a tool must start with the whole call before it<br>second = add_tool_result(ana, PANTRY_CALL, PANTRY_RESULT)<br>assert second[&quot;messages&quot;][:2] == ana[&quot;messages&quot;]</pre><p>If someone later puts the date back on top, writes a name into the instructions or trims the tool list for one plan, the first check fails. If someone rebuilds the prompt after a tool call, the second one does.</p><h3>How we did it in our own agents</h3><p>In <a href="https://medium.com/@baigorria/rent-the-model-own-the-harness-how-to-build-a-model-agnostic-ai-agent-7c921a888e61">an earlier post on owning the harness</a> we said caching deserved a post of its own. This October we made the same kind of moves on our real agents: the time went to the end of each request, the tool definitions stopped varying by project, role or language, and each tool call adds to the request instead of rebuilding it.</p><blockquote><em>A tool call should add to the request, never rebuild it.</em></blockquote><p>We saw even more improvement than in this small evening, because our agents often make more than one tool call for each message, and those are the calls that read the most from the cache. The more tool calls, the higher the average. Our dashboard went from the 60s to 93%. What we are building is still in development, with few people and long gaps between messages, so many calls find the cache expired, like Ana’s first message of the evening; with continuous use we expect 96 to 98%.</p><figure><img alt="Before and after: the same agent and rules in another order. Before, every call read 0% from the cache; after, the call after the tool read 94%." src="https://cdn-images-1.medium.com/max/1024/1*-fMw0vz15U6WmLv74ck-bw.png" /></figure><p>Look at the first lines of your prompt. If they change from one call to the next, move them to the end, and let the cache do the rest.</p><p>Originally published at <a href="https://blog.getwerk.ai/posts/prompt-caching-a-quarter-of-the-bill">blog.getwerk.ai</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=22494c6803fa" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What Google’s Harness² shows about improving an AI agent]]></title>
            <link>https://generativeai.pub/what-googles-harness%C2%B2-shows-about-improving-an-ai-agent-4191873249b1?source=rss-c4d55ae2e0bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/4191873249b1</guid>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[large-language-models]]></category>
            <dc:creator><![CDATA[Guillermo Baigorria]]></dc:creator>
            <pubDate>Thu, 29 Oct 2026 19:23:43 GMT</pubDate>
            <atom:updated>2026-10-30T03:15:49.910Z</atom:updated>
            <content:encoded><![CDATA[<h4>The gains came from scripts and skills, not the prompt. And letting the model rewrite its harness blindly made it worse.</h4><figure><img alt="Bar chart: removing the skills from the improved Harness2 harness costs 5.3 points, the scripts 3.7 and the prompt-related components 1.5." src="https://cdn-images-1.medium.com/max/1024/1*9cfskkkMERPmlgvrhAMgoQ.png" /></figure><p>Harness² is a framework from Google Cloud AI Research and Northwestern University that improves an AI agent without touching the model. The model stays frozen; only its harness changes: the prompts, tools, skills, and scripts around it. On WorkBuddy-Bench, a benchmark of office, web, and coding tasks, that alone raised GLM-5’s average score by 11.5 points.</p><p>I made the same argument in the <a href="https://medium.com/@baigorria/rent-the-model-own-the-harness-how-to-build-a-model-agnostic-ai-agent-7c921a888e61">first post of my series on building a harness</a>: the model is rented, the harness is yours. The next parts cover how a message reaches the right agent and how to test a harness that learns from its mistakes.</p><p>Most summaries of Harness² stop at the headline. I read <a href="https://arxiv.org/abs/2610.14224">the paper</a> (2026) and <a href="https://github.com/google-research/harness2">its code</a> to see where the gains came from, because that is the part any team can use without running the framework.</p><h4>How Harness² improves a harness without an answer key</h4><p>Harness² works one task at a time. An editor model writes a few versions of the harness for the task in front of it, the same frozen model runs the task under each version, and the framework compares how the runs behaved: what each one read, did, and produced.</p><p>It then combines the changes that helped. There is no answer key: it judges by behavior.</p><p>What worked goes into a library. Each entry holds the adopted harness and a short EXPERIENCE.md file with the situation the lesson applies to, the lesson itself, and the evidence behind it. The next task starts again from the clean base harness, but the editor reads the library before proposing anything.</p><p>It does not need a stronger model to do the editing. With the same model as executor and editor, every model they tried improved, and GLM-5 editing its own harness gained 13.7 points on LAB, a benchmark of legal work.</p><h4>Editing a harness without evidence made it worse</h4><p>The paper also tried the shortcut: let the editor rewrite the base harness directly, without seeing any runs, any probes or the library. On coding tasks, the score fell from 73.4 to 63.2, and on web tasks from 69.9 to 65.0. Asked to improve its own setup blind, the model made it worse.</p><p>That matches what I have seen building agents. When an agent fails, the first instinct is to add a line to its prompt, before looking at what it actually received and what it did. Harness² is built the other way around: every change comes from comparing real runs.</p><p>It is careful even with its own winners. The step that writes the lessons is told that being picked is not proof an edit helped: the chosen run may have won for another reason. A lesson that rests only on mixed evidence is narrowed or dropped.</p><blockquote><em>Rewriting the harness without seeing any runs dropped the coding score from 73.4 to 63.2. (Harness², 2026)</em></blockquote><h4>The gains were in scripts and skills, not in the prompt</h4><p>In an appendix (Table 6), the authors take the improved harness and remove one group of components at a time. Removing the prompt-related components costs 1.5 points on average. Removing the skills costs 5.3, and removing the scripts 3.7.</p><p>It is one setup, Gemini 3.5 Flash on WorkBuddy-Bench, and the authors note the effects do not simply add up, but the prompt carried the least.</p><p>A script, in their terms, is code the agent runs instead of reasoning through a step token by token. A skill is a procedure for one kind of job, loaded only when that job comes up. Both are more specific than a prompt, which the model reads on every call whether it needs it or not.</p><p>In my experience, a rule added to a prompt tends to fix the case it came from, and a check in code holds every time. The paper’s own case study shows it.</p><p>On a JobBench task, the agent never reopened the spreadsheets it wrote. The improved harness added, among other changes, verify_outputs.py: a script that reopens every file the agent produced and flags, for example, a formula cell a reader would see blank.</p><p>Its rule reads: confirming a file exists is not confirming it is correct. The score on that task went from 43.1 to 77.8.</p><blockquote><em>Removing the skills cost 5.3 points. Removing the prompt-related components cost 1.5. (Harness², 2026)</em></blockquote><h4>Write the fact, not the instruction to find it</h4><p>The editor’s instructions are printed in the paper’s appendix, and one line stands out: verified facts about the workspace are “the most valuable thing you can encode”.</p><p>If the runs established that the role “HR” in one file maps to “HR Manager” in another, the editor writes that mapping into the harness, not a rule telling the agent to reconcile role names. The rule leaves the hardest step to the agent; the fact removes it.</p><p>It also labels those facts (“in this workspace…”) and treats a fact copied from an earlier task as a hypothesis to check again. This is a design choice in their instructions, not a measured result, but it is the one I would copy first: many agent mistakes that look like poor reasoning are a fact the model never saw.</p><h4>What Harness² leaves open</h4><p>Lessons are written once. An EXPERIENCE.md entry keeps the confidence it was given when it was written, and nothing changes it when a later task reuses the lesson, and it goes badly. The authors list revising outdated experience as future work.</p><p>Its judge is the model itself. The limitations section says plainly that behavioral comparisons are “sensitive to execution variability and shared model biases”, and every probe adds runs and cost.</p><p>It also answers the question of learning without retraining differently from <a href="https://github.com/NousResearch/hermes-agent">Hermes Agent</a>, which I read for the first post. Hermes writes skills after a session and keeps them for the next ones. Harness² starts every task from a clean harness and tests candidates before it adopts anything.</p><h4>What to take from it without the framework</h4><p>You can use what Harness² found without running it: look at what the agent received and did before changing anything, move what must happen the same way every time out of the prompt and into code, and give the agent the fact instead of the instruction to find it.</p><p>In every comparison in the paper, the model stayed the same. What moved the score was what the harness gave it to work with.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*Z5WrEPxIqey5t86l.png" /></figure><p>This story is published under the <a href="https://generativeai.pub/">Generative AI</a> publication. Connect with us on <a href="https://www.linkedin.com/company/generative-ai-publication">LinkedIn</a> and follow <a href="https://www.zeniteq.com/">Zeniteq</a> to stay in the loop with the latest AI stories. Let’s shape the future of AI together!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*gkQOUrEraRWt9Bko.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4191873249b1" width="1" height="1" alt=""><hr><p><a href="https://generativeai.pub/what-googles-harness%C2%B2-shows-about-improving-an-ai-agent-4191873249b1">What Google’s Harness² shows about improving an AI agent</a> was originally published in <a href="https://generativeai.pub/">Generative AI</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Rent the model, own the harness: how to build a model-agnostic AI agent]]></title>
            <link>https://medium.com/@baigorria/rent-the-model-own-the-harness-how-to-build-a-model-agnostic-ai-agent-7c921a888e61?source=rss-c4d55ae2e0bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/7c921a888e61</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Guillermo Baigorria]]></dc:creator>
            <pubDate>Wed, 28 Oct 2026 17:36:00 GMT</pubDate>
            <atom:updated>2026-10-29T19:44:07.563Z</atom:updated>
            <content:encoded><![CDATA[<h4>Models change every few months. Four practices that keep an agent working whatever model sits behind it.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*X47vvDB4KtvFErzO2bz7BQ.jpeg" /><figcaption>Image created with AI.</figcaption></figure><p>Developers have Claude Code or Codex. Office workers have Claude Cowork or ChatGPT Work. Each of these is a harness: the scaffolding around an AI model that lets it do real work, with tools, context and rules. The person installing solar panels on a roof has nothing built for their work.</p><p>At Werk we built one for teams on the move, and our first decision was to keep it separate from the model: the model understands and proposes, and the harness decides what it reads, what it touches and what gets recorded. Four practices make that possible: talk to models through an interface of your own, have each agent ask for a level of work instead of a model, give every model the same format, and put what stays the same first. This post starts a series on how it is built. Why Werk exists is in <a href="https://blog.getwerk.ai/posts/why-we-built-werk">Why we built Werk</a>.</p><h3>What the model does and what the harness does</h3><p>Take a four-second voice note recorded on a roof: “Done with the Novak job.” Getting that sentence recorded correctly takes two different kinds of work.</p><p>The model understands the request: a job is finished, and of the cards in front of it, Novak’s is the one being named. The harness does everything else. It chooses which cards to show the model, checks that this person may change the card, records the change once even if the message is processed twice, and tells whoever needs to know.</p><p>A <a href="https://arxiv.org/abs/2609.00006">study published on arXiv</a> in 2026 read the source code of eleven coding harnesses, including Claude Code, Codex, Gemini CLI, Hermes and Pi. It defines a harness as what connects a model to tools, context, safety, orchestration and extensions. Put simply: the model understands and proposes. The harness decides what it reads, what it touches and what gets recorded.</p><p>The same study found that none of the eleven harnesses studied imports a general-purpose agent framework; all of them run hand-written loops. Anthropic reached the same conclusion in <a href="https://www.anthropic.com/engineering/building-effective-agents">Building effective agents</a> (2024): the most successful implementations it saw did not use complex frameworks, and its advice is to start by calling model APIs directly.</p><h3>How to keep the harness separate from the model</h3><p>If the harness makes the decisions, it should not depend on any one model. Models improve every few months, no model is best at everything, and no cloud service is up 100% of the time, as providers report openly on their status pages, such as <a href="https://status.claude.com/history">Anthropic’s</a> and <a href="https://status.openai.com/history">OpenAI’s</a>. These are the four practices that keep the Novak note working whatever model is behind it.</p><p>We arrived at them by reading the code of more than fifteen open-source projects (MIT or Apache 2.0), such as Codex, Gemini CLI, OpenHands, Aider and Pi, and the documentation of others. We took ideas, not code.</p><p>The first is to talk to models through an interface of your own. No part of the harness calls a provider directly: <strong>the provider is configuration</strong>. We work with the major providers in the industry, and moving from one to another is a configuration change we measure before we make it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LVV-m7UI4AjaCSJO.png" /></figure><p>The second is that each agent asks for a level of work, not a model. The agent that marks Novak’s card as done does not know which model serves it. It declares the level it needs, and our battery of test cases decides, agent by agent, which model fills that slot.</p><p>The third is a format every model reads the same way. We follow what the industry recommends, for example the guides from <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices">Anthropic</a> and <a href="https://developers.openai.com/api/docs/guides/prompt-engineering">OpenAI</a>: each kind of data inside its own tag, so the model knows where each piece starts and ends. The conversation, the cards and the voice note reach any model in the same shape.</p><blockquote>None of the eleven harnesses studied imports a general-purpose agent framework. (Barbaste, Darrigol, Vu and Wiltberger, 2026)</blockquote><p>The fourth is to put what stays the same first and what changes last. Each agent’s instructions are identical on every message; the Novak note is not. With the stable part first, the provider reuses what it has already processed, so the answer arrives sooner and costs less: with <a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness</a>, one user <a href="https://github.com/deepseek-ai/deepseek-harness/discussions/2064">measured a 98% cache hit rate</a> across 650 requests. Cache optimization deserves a post of its own, and we will write it.</p><h3>What no SDK can solve for you</h3><p>Agent SDKs such as the <a href="https://openai.github.io/openai-agents-python/">OpenAI Agents SDK</a> and the <a href="https://github.com/anthropics/claude-agent-sdk-python">Claude Agent SDK</a> are a great way to start: they handle the cycle of calling the model, running tools and repeating. We studied them closely, along with LangGraph, the Vercel AI SDK, Pydantic AI and Mastra. But the hardest part of the Novak note is not in that cycle.</p><p>It is in what belongs to a team. Novak’s card lives in a record that several people share, each with their own permissions. If Werk asks which of two cards was meant and the answer comes back as “the second one,” that answer has to stay tied to what that person saw on screen. That depends on each product, and the good SDKs say so plainly: <a href="https://mastra.ai/docs/agents/agent-approval">Mastra’s documentation</a> recommends binding an approval to the exact arguments the approver saw.</p><p>A personal agent is not enough either. <a href="https://github.com/NousResearch/hermes-agent">Hermes Agent</a> and <a href="https://github.com/openclaw/openclaw">OpenClaw</a>, two of the open-source projects we read, are built for one person. Hermes says so in its <a href="https://github.com/NousResearch/hermes-agent/blob/main/SECURITY.md">security policy</a>: it is a single-tenant personal agent, and everyone with access is equally trusted. For a personal agent, that is the right call. On a team, each person sees their own work and what the project shares, and the model never decides who sees what.</p><blockquote>The model understands and proposes. The harness decides what it reads, what it touches and what gets recorded.</blockquote><p>That is why we built our own harness, and why the next part of this series covers its central piece: the router, which receives the Novak note and hands it to the right agent.</p><h3>The model changes, the harness stays</h3><p>Because the important decisions live in the harness, the model can be chosen, compared and replaced when a better one comes along. The harness is what is yours: what each agent reads, what the code checks before touching the record, how an error is caught and how it is fixed without breaking something else.</p><p>Models will keep getting better. With a well-separated harness, each improvement reaches daily use on its own: a voice note understood better, the right card, the notice to whoever needs to know.</p><p>Teams that use Werk do not have to do anything to benefit. The harness does that work.</p><p><em>Originally published at </em><a href="https://blog.getwerk.ai/posts/rent-the-model-own-the-harness"><em>https://blog.getwerk.ai</em></a><em> on October 28, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7c921a888e61" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>