Subtrahera, anpassa, bevisa: tre färdigheter som hindrar AI-agenter från att spaghettifiera ditt repo

Publicerad den Jul 1, 2026 av Štefan Moravík.
AI Agents Developer Productivity Agentic Workflows Code Review
På den här sidan 11 min läsning
  1. 1Del 1 · VAD — entropi är standardläget
  2. 2Del 2 · SÅ VAD — fem PR:er, en instinkt var
  3. 3Del 3 · VAD NU

Vi ger kodagenter riktiga ärenden varje dag, och de levererar nästan alltid något som fungerar. Det var aldrig oron. Oron är hur de arbetar: en ny hjälpfunktion bredvid tre som redan gör jobbet, en ny abstraktion för en enda anropare, en fix som lagar den enda väg ärendet nämnde och lämnar fyra syskon trasiga, ett fynd som är “förmodligen en bugg” utan bevis i någon riktning. Varje ändring är lokalt rimlig. I aggregerad form är de entropi.

TL;DR: I fem Tier-3-pull requests i vår agentorkestreringkärna tog tre komponerbara färdigheter — ponytail (subtrahera), grain (anpassa) och review-proof (bevisa) — bort 821 rader samtidigt som de levererade fem funktioner, fångade en tyst kontraktsbrytning som enbart rimlighet hade mergat, och höll varje ändring i linje med den befintliga arkitekturen. Här är vad var och en gör, med de verkliga diffarna som stöd.

Tar man bort skyddsräcken är en kodagent en mycket snabb generator av rimligt utseende skulder. Så vi lutar oss mot tre små färdigheter som trycker i motsatt riktning — en instinkt var: subtrahera, anpassa, bevisa.

  • ponytail — skriv det lataste som faktiskt fungerar. Radera innan du lägger till. (Vi skrev inte den här — det är en färdighet med öppen källkod av Dietrich Gebert som vi anpassat för vår stack.)
  • grain / grain-review — placera det där kodbasen redan har bestämt att det hör hemma. Uppfinn inte ett andra sätt.
  • review-proof — tro inte på ett fynd förrän det reproduceras som ett fallerande test.

grain och review-proof byggde vi i samma anda som ponytail, anpassade till vår arkitektur. Var och en av de fem PR:erna nedan rör vår agentorkestreringkärna — den enskilt dyraste platsen i repot att vara slarvig i — och alla är klassade som Tier 3: extra testtäckning och mänsklig granskning ovanpå den automatiska granskaren, utan undantag.

Tre färdigheter för kodagenter, en instinkt var: ponytail subtraherar, grain anpassar, review-proof bevisar — med vad var och en dödar och dess avkastning

De tre färdigheterna i korthet: ponytail subtraherar, grain anpassar, review-proof bevisar.

Del 1 · VAD — entropi är standardläget

Här är saken ingen varnar dig om när du lämnar ett repo till AI-agenter: varje agent optimerar lokalt och minns ingenting. Den ser ärendet, inte de månader av konventioner som ditt team har enats om. Den har ingen anledning att föredra din befintliga e-posttjänst framför en ny, inget minne av att uppsättningen av omdirigeringsstatusar redan är definierad tre filer bort, ingen instinkt att “fixen hör hemma i den delade funktionen, inte hos den här anroparen”. Lämnade att köra fritt producerar N agenter N något olika sätt att göra samma sak. Det är inte ett kodkvalitetsproblem du kan linta bort — det är en strukturell drift som förstärks över tid.

De tre färdigheterna riktar sig var och en mot en axel av den driften.

ponytail — det lataste som fungerar

Ponytail är en senior utvecklare som har blivit väckt klockan tre på natten för någon annans smarta abstraktion och som vägrar skriva nästa. Den följer en stege och stannar vid första steget som håller: behöver detta existera alls (YAGNI) → finns det redan i den här kodbasen → gör standardbiblioteket det → inbyggd plattformsfunktion → redan installerat beroende → kan det vara en rad → först då, den minsta kod som fungerar.

Steget som betyder mest för agenter är “finns det redan i den här kodbasen?” Att återimplementera något som ligger några filer bort är den enskilt vanligaste formen av agentslarv. Och ponytails buggfix-regel håller diffarna ärliga: fixa grundorsaken, inte symptomet. Grep:a varje anropare av funktionen du är på väg att röra; en guard i den delade funktionen är en mindre diff än en guard hos varje anropare — och den lämnar inte syskonen trasiga.

grain / grain-review — gå med fibern

Om ponytail styr hur lite du skriver, styr grain var det hamnar och vilken form det tar. Dess enda regel: hitta det närmaste befintliga exemplet, kopiera dess form, namnge vad du kopierade. Ny kod ska läsas som om personen som skrev filen bredvid också skrev den här.

Grain är också där arkitekturen upprätthålls. Vår backend är en ganska standardmässig vertical-slice + hexagonal layout — presentation anropar applikation anropar domän, infrastruktur är beroende inåt, och domänen når aldrig utåt igen. Ett fynd som “den här routen hoppar över sin controller och hämtar tjänsten direkt” är inte pedanteri — det är skillnaden mellan en kodbas som en agent kan navigera i nästa månad och en den inte kan. grain-review jagar exakt dessa: duplicerade hjälpfunktioner, korsade lagergränser, att nå in i en annan funktions interna delar, en andra konvention för något som redan görs på ett sätt.

review-proof — förtjäna fyndet

Standardmässig AI-kodgranskning producerar rimliga fynd. Vissa är verkliga; vissa är självsäkert nonsens; utifrån ser de identiska ut. review-proof vägrar lita på sig själv: den granskar, och tvingar sedan varje korrekthetsfynd att reproduceras som ett verkligt fallerande test eller en körbar repro, och släpper allt som inte gör det. Den avslutar med en grain-review-omgång för strukturell passform. Det som levereras är en granskning där varje punkt kommer med körbara bevis — inte en känsla.

Vad vi borde se om detta fungerar

  • H1 — Radering syns i funktions-PR:er. Om ponytail + grain fungerar bör det att lägga till en funktion ofta ta bort nettostruktur, inte bara lägga till.
  • H2 — Fixar landar en gång, på den delade platsen. Grundorsaksfixar bör kollapsa många anropsställen till en enda guard, inte strö ut guards per anropare.
  • H3 — Granskningen fångar kontraktsbrytningar som en människa skummar förbi. Bevisunderstödd granskning bör lyfta fram buggar som en “ser bra ut”-granskning missar — särskilt de tysta.

Del 2 · SÅ VAD — fem PR:er, en instinkt var

Fem verkliga ändringar i vår agentkärna. Vi håller internerna vaga med avsikt — repot är privat — men siffrorna är beräknade från de faktiska diffarna och lärdomarna är den överförbara delen.

Subtrahera: en guard för ett dussin fetch-ställen

En familj av flödessteg hämtade användartillhandahållna URL:er utan en DNS-uppslagningssäkerhetskontroll, så ett värdnamn som löstes upp till en intern adress kunde nå molnmetadata från backend. Den frestande fixen lägger till en kontroll på vart och ett av de dussintalet fetch-ställen. Ponytails svar var det motsatta: en delad, skyddad fetch-hjälpfunktion, använd överallt — och vi tog bort en handrullad tabell över privata nätverk som ett wildcard-DNS-trick gick rakt förbi, plus tre duplicerade omdirigeringsloopar och en nätverkskontroll som klistrats in i flera filer.

Diffen lade till den delade hjälpfunktionen och tog bort ~90 rader duplicering över 22 filer. Den raderingen är själva historien: detta är H2 i kött och blod — grundorsaksfixen ledde varje anropare genom en enda guard i stället för att lappa den enda väg ärendet nämnde.

Ett dussin fetch-ställen för användar-URL:er, vart och ett med sin egen kringgåbara kontroll, mynnar ut i en delad skyddad fetch-hjälpfunktion

Grundorsaksfixen: ett dussin ad hoc-fetch-ställen kollapsar till en delad, skyddad hjälpfunktion. Den lata fixen och den säkra fixen är samma fix.

Subtrahera + bevisa: en form-guard, bevisad i den verkliga körmiljön

Vår worker-körmiljö sparar ett körningsresultat som en serialiserad sträng, ibland inlindad i en lista med ett enda element. Konsumenter som förväntade sig ett vanligt objekt kraschade på det. Den felaktiga fixen sprider ut defensiva typkontroller hos varje konsument. I stället: en liten formnormaliserande hjälpfunktion, och varje konsument ompekad mot den — ett nästan renodlat tillägg av en guard som ersätter de N ad hoc-guards en mindre disciplinerad agent skulle ha skrivit (+558 / −24, 7 filer).

Delen som gör detta till en review-proof-historia är testet. I stället för att asserta mot en antagen serialiseringsform körde vi ett verkligt arbetsflöde genom den faktiska körmiljön och lagringen — inga mocks — och bevisade den form som körmiljön faktiskt sparar. Den öppna frågan i ärendet var bokstavligen vad serialiserar körmiljön här? — och det enda ärliga svaret är ett du kan köra.

Bevisa: granskningen fångade en tyst kontraktsbrytning

Funktion: en fallback-modell per nod, så att ett flöde som är låst till en leverantör kan degradera smidigt vid ett avbrott. Den uppenbara första versionen lindade in modellen i ramverkets inbyggda fallback-kombinator.

Den fungerade i happy path. Den stängde också tyst av två leverantörsfunktioner som styrs av den konkreta modelltypen via isinstance — ett inlindat objekt är inte längre den typen, så både inbyggd strukturerad output och prompt-cachning stängdes tyst av. Inget fel. Inget fallerande happy-path-test. Exakt den sortens sak som en mänsklig granskning skummar förbi och en “ser bra ut”-agent godkänner.

review-proof godkände den inte — den reproducerade båda brytningarna som fallerande tester, vilket tvingade fram en omdesign: applicera fallbacken längre ner, vid exekveringstid, så att varje modell behåller sin konkreta typ och de typstyrda funktionerna fortsätter fungera. H3, bekräftat med bestämdhet: beviset fångade en bugg som rimlighet hade levererat.

Anpassa: en väljare, inte två kopior

Att lägga till en andra aviseringskanal innebar att kanalväljarens UI nu hade två hem — en skapa-guide och en inställningsmodal. Agentens standarddrag lägger till den nya grenen i båda, vilket odlar två kopior av samma tillståndsmaskin. grain sade: det finns redan ett sätt detta borde formas på — gör det delat. Vi extraherade en enda väljar-hook och drev båda skärmarna genom den, stoppade in den nya kanalen i den befintliga konfigurationsunionen och återanvände den befintliga e-posttjänsten i stället för att lägga till ny sändningsmekanik.

+1 735 / −340 över 24 filer. En funktion av den här storleken som tar bort 340 rader är H1 synliggjort: dedupen av två väljarkopior till en betalade för en bra del av den nya kanalen.

Anpassa + bevisa: återanvänd endpointen, spegla vägen

Att låta användare bifoga filer vid ärendeskapande kunde ha inneburit en ny upload-endpoint, en ny dispatch-mekanism, en ny prompt-väg. grain ledde nästan allt in på befintliga räls: den befintliga upload-endpointen, en frontend-acceptlista som spegla backendens vitlista exakt, och en deferred-dispatch-fix som återanvände den behörighetsmekanism som schemalagt arbete redan använde. Den levererades med bevisunderstödda fixar, inklusive en verklig transaktionsisoleringsbugg som skulle ha förlorat data vid parallella uppladdningar. +1 776 / −218 över 27 filer — en stor funktion som ändå hittade 218 rader att ta bort genom att ansluta till befintliga skivor i stället för att uppfinna nya.

Resultattavlan

Resultattavla över fem Tier-3-PR:er som visar tillagda och borttagna rader per PR, plus instinkten som formade var och en: subtrahera, anpassa eller bevisa

Fem Tier-3-PR:er: vad var och en lade till, vad den tog bort, och instinkten bakom.

Fem funktions- och fix-PR:er i agentkärnan tog bort 821 rader — inte genom att göra mindre, utan genom att vägra duplicera det som redan fanns och genom att inte behålla symptomlappningar som en grundorsaksfix gjort överflödiga.

Full öppenhet

  • Detta är färdigheter, inte en studie. Det här är inte ett kontrollerat experiment med en baslinjegrupp; det är fem verkliga PR:er där disciplinen tillämpades. Kontrafaktualiteten — vad samma agent skulle ha levererat utan färdigheterna — är en informerad uppskattning, inte en mätning. Historien om den tysta kontraktsbrytningen är det renaste beviset, eftersom vi såg granskningen reproducera buggen före omdesignen.
  • Radantal är proxysiffror. −821 är ett verkligt tal från diffarna, men “rader borttagna” står för “duplicering och död flexibilitet undviken”. En färdighet som övertalar en agent att inte skriva 200 spekulativa rader lämnar inga spår i en diff alls — de största vinsterna är osynliga här.
  • Tokenbesparingar är riktningsvisande. Mindre diffar, färre berörda filer och återanvända strukturer innebär färre tokens som spenderas på att generera, granska och granska igen — men vi citerar ingen hård token-delta per PR.
  • ponytail är inte vår. Det är en färdighet med öppen källkod av Dietrich Gebert ; vi anpassade den. grain och review-proof är våra, byggda i samma anda. Alla tre körs som lokala projektfärdigheter på Claude Code — prompt och procedur, inte en binär du installerar.
FlowHunt Logotyp

Redo att växa ditt företag?

Starta din kostnadsfria provperiod idag och se resultat inom några dagar.

Del 3 · VAD NU

Vad som levererades. Tre komponerbara färdigheter. ponytail och grain körs medan du skriver; ponytail-review, grain-review och review-proof körs på en diff. review-proof kedjar grain-review som sin sista fas, så en enda bevisad granskning också får en strukturell genomgång på köpet.

Vad du kan göra på måndag — du behöver inte våra exakta färdigheter:

  1. Gör “återanvänd” till steg två, inte steg tio. Innan en agent skriver en hjälpfunktion, låt den grep:a efter en som finns. “Finns det redan i den här kodbasen?” hör ovan “kan jag skriva det snyggt?”
  2. Fixa vid roten, bevisa det med anropslistan. Kräv att varje buggfix namnger varje anropare av den berörda funktionen. En guard i den delade funktionen slår en guard per anropare — och det är en mindre diff.
  3. Ge ny kod ett närmaste syskon att kopiera. “Hitta det närmaste befintliga exemplet och spegla dess form” gör arkitektur från ett dokument ingen läser till ett standardbeteende agenten följer.
  4. Upprätthåll lagergränser i CI, inte på känsla. En spärr som bara fallerar på nya korsande lagerimporter låter dig hålla linjen utan att koka havet av befintlig skuld.
  5. Leverera inte ett fynd du inte kan reproducera. Låt agenten skriva det fallerande testet först. Om den inte kan få buggen att reproducera är det inte en bugg — det är en åsikt. Släpp den.
  6. Låt granskningen radera. Rikta en granskningsomgång specifikt mot överengineering — “vad kan vi skära bort” — separat från korrekthet. Det bästa utfallet av en diff är att den blir kortare.

Prova, särskilt om det misslyckas för dig. Om du kör kodagenter på en verklig kodbas händer entropin redan — du har bara inte mätt den. Gör en av dessa till en granskningsomgång på dina nästa tio agent-PR:er och räkna raderingarna. Om subtrahera-anpassa-bevisa inte krymper dina diffar eller fångar en tyst brytning vill vi verkligen höra det. Rättelser och motexempel är särskilt välkomna.

En agent lägger till. Jobbet är att få agenten att förtjäna varje rad.

Vanliga frågor

Štefan är en AI- och mjukvaruingenjör som bygger FlowHunt. Bortom produkten själv designar han agentic software-engineering-arbetsflöden för utvecklare som minskar utvecklingskostnaderna samtidigt som kodkvaliteten ökar.

Štefan Moravík
Štefan Moravík
AI- och mjukvaruingenjör

Bygg agentarbetsflöden som betalar sig själva

FlowHunt hjälper utvecklingsteam att designa agentiska arbetsflöden, granskningsgrindar och MCP-integrationer som sänker utvecklingskostnaderna samtidigt som de höjer kodkvaliteten.