Harness engineering: udnyttelse af Codex i en agent-først-verden
Af Ryan Lopopolo, teknisk medarbejder
I de sidste fem måneder har vores team udført et eksperiment om, at udvikle og levere en intern beta af et softwareprodukt med 0 linjer manuelt skrevet kode.
Produktet har interne daglige brugere og eksterne alfatestere. Det leveres, udrulles, går i stykker, og bliver rettet. Det, der er anderledes, er, at hver linje kode (applikationslogik, tests, CI-konfiguration, dokumentation, observability og interne værktøjer) er skrevet af Codex. Vi vurderer, at vi byggede dette på omkring en tiendedel af den tid, det ville have taget at skrive koden i hånden.
Mennesker styrer. Agenter udfører.
Vi valgte bevidst denne begrænsning, så vi kunne bygge det nødvendige for at øge ingeniørhastigheden med størrelsesordener. Vi havde uger til at levere det, der endte med at være en million kodelinjer. For at kunne gøre det skulle vi forstå, hvad der ændrer sig, når et softwareingeniørteams primære opgave ikke længere er at skrive kode, men at designe miljøer, specificere intentioner og opbygge feedbacksløjfer, der gør det muligt for Codex-agenter at udføre pålideligt arbejde.
Dette indlæg handler om, hvad vi lærte ved at bygge et helt nyt produkt med et team af agenter og hvad der gik i stykker, hvad der blev forstærket, og hvordan vi maksimerer vores eneste virkelig knappe ressource: menneskelig tid og årvågenhed.
Den første commit til et tomt lager blev foretaget i slutningen af august 2025.
Den indledende struktur (med lagerstruktur, CI-konfiguration, formateringsregler, opsætning af pakkehåndtering og applikationsramme) blev genereret af Codex CLI ved hjælp af GPT‑5, vejledt af et lille sæt eksisterende skabeloner. Selv den første AGENTS.md-fil, der vejleder agenter om, hvordan de skal arbejde i lageret, blev skrevet af Codex.
Der var ingen forudgående menneskeskrevet kode til at forankre systemet. Helt fra begyndelsen blev lageret formet af agenten.
Fem måneder senere indeholder lageret omkring en million linjer kode fordelt på applikationslogik, infrastruktur, værktøjer, dokumentation og interne udviklerværktøjer. I løbet af den periode er der blevet åbnet og fusioneret cirka 1.500 pull requests, hvor et lille team på blot tre ingeniører har drevet Codex. Dette svarer til et gennemsnitligt gennemløb på 3,5 PR'er pr. ingeniør pr. dag, og overraskende nok er gennemløbet steget, efterhånden som teamet er vokset til nu syv ingeniører. Det var vigtigt, at dette ikke var output for blot outputtets skyld: Produktet er blevet brugt af hundredvis af brugere internt, herunder daglige interne superbrugere.
Gennem hele udviklingsprocessen bidrog mennesker aldrig direkte med nogen kode. Dette blev en kernefilosofi for teamet: ingen manuelt skrevet kode.
Manglen på praktisk, menneskelig kodning introducerede en anden type ingeniørarbejde med fokus på systemer, stilladser og udnyttelse.
De tidlige fremskridt var langsommere, end vi havde forventet, ikke fordi Codex var ude af stand til det, men fordi miljøet var underspecificeret. Agenten manglede de værktøjer, abstraktioner og den interne struktur, der var nødvendig for at gøre fremskridt mod højniveau mål. Den primære opgave for vores ingeniørteam blev at gøre det muligt for agenterne at udføre nyttigt arbejde.
I praksis betød dette først og fremmest at arbejde i dybden såsom at opdele større mål i mindre byggesten (design, kode, gennemgang, test osv.), at tilskynde agenten til at konstruere disse blokke og bruge dem til at låse op for mere komplekse opgaver. Når noget gik galt, var løsningen næsten aldrig “prøv hårdere.” Fordi den eneste måde at gøre fremskridt på var at få Codex til at udføre arbejdet, trådte menneskelige ingeniører altid ind i opgaven og spurgte: “hvilken kapacitet mangler, og hvordan gør vi den både læsbar og brugbar for agenten?”
Mennesker interagerer med systemet næsten udelukkende gennem prompts: en ingeniør beskriver en opgave, kører agenten og lader den åbne en pull request (PR). For at afslutte en PR instruerer vi Codex i at gennemgå sine egne ændringer lokalt, anmode om yderligere specifikke agentgennemgange både lokalt og i skyen, reagere på al feedback fra mennesker eller agenter og gentage processen i et loop, indtil alle agentanmeldere er tilfredse (dette er i praksis et Ralph Wiggum-loop(åbner i et nyt vindue)). Codex bruger vores standardudviklingsværktøjer direkte (gh, lokale scripts og lagerindlejrede færdigheder) til at indsamle kontekst uden at mennesker kopierer og indsætter i CLI.
Mennesker kan gennemgå pull requests, men behøver ikke at gøre det. Over tid har vi flyttet næsten alle gennemgangsindsatser til at blive håndteret agent-til-agent.
Efterhånden som kodegennemløbet steg, blev vores flaskehals den menneskelige QA-kapacitet. Eftersom den faste begrænsning har været menneskelig tid og årvågenhed, har vi arbejdet på at tilføje flere funktioner til agenten ved at gøre ting såsom applikationens brugerflade, logfiler og app-målinger, der er direkte læsbare for Codex.
For eksempel gjorde vi appen bootbar pr. git worktree, så Codex kunne starte og køre én instans pr. ændring. Vi integrerede også Chrome DevTools-protokollen i agentens runtime og skabte færdigheder til at arbejde med DOM-snapshots, skærmbilleder og navigation. Dette gjorde det muligt for Codex at genskabe fejl, validere rettelser og analysere UI-adfærd direkte.

Vi gjorde det samme for observationsværktøjer. Logs, metrics og traces eksponeres til Codex via en lokal observerbarhedsstak, der er midlertidig for enhver given worktree. Codex arbejder på en fuldt isoleret version af den app, inklusive dens logfiler og målinger, som bliver fjernet, når opgaven er fuldført. Agenter kan forespørge logfiler med LogQL og metrikker med PromQL. Når denne kontekst er tilgængelig, bliver prompts såsom “sørg for, at opstart af tjenesten gennemføres på under 800 ms” eller “intet tidsrum i disse fire kritiske brugerrejser overstiger to sekunder” håndterbare.
Vi ser ofte, at enkelte Codex-kørsler arbejder på en enkelt opgave i op til seks timer (ofte mens mennesker sover).
Konteksthåndtering er en af de største udfordringer ved at gøre agenter effektive til store og komplekse opgaver. En af de første ting, vi lærte, var enkel: giv Codex et kort, ikke en instruktionsmanual på 1.000 sider.
Vi brugte "én stor AGENTS.md(åbner i et nyt vindue)"- strategien. Det fejlede på forudsigelige måder:
- Kontekst er en knap ressource. En kæmpe instruktionsfil skubber opgaven, koden og den relevante dokumentation til side, så agenten enten overser vigtige begrænsninger eller begynder at optimere efter de forkerte.
- For meget vejledning bliver ikke-vejledning. Når alt er 'vigtigt', bliver intet det. Agenter ender med at mønstergenkende lokalt i stedet for at navigere målrettet.
- Det 'rådner' øjeblikkeligt. En monolitisk manual bliver til en kirkegård af forældede regler. Agenter kan ikke afgøre, hvad der stadig er sandt, mennesker holder op med at vedligeholde det, og filen bliver stille og roligt en attraktiv gene.
- Det er svært at verificere. En enkelt blob egner sig ikke til mekaniske kontrolprocedurer (dækning, aktualitet, ejerskab, krydshenvisninger), så afvigelser er uundgåelige.
Så i stedet for at behandle AGENTS.md som et leksikon, behandler vi det som en indholdsfortegnelse.
Lagerets vidensbase findes i en struktureret docs/-mappe, der fungerer som det primære registreringssystem. En kort AGENTS.md (omtrent 100 linjer) indsættes i konteksten og fungerer primært som et kort med henvisninger til dybere sandhedskilder andre steder.
Designdokumentation katalogiseres og indekseres, inklusive verifikationsstatus og et sæt kerneoverbevisninger, der definerer agent-først driftsprincipper. Arkitekturdokumentation(åbner i et nyt vindue) giver et overordnet kort over domæner og pakke-lagdeling. Et kvalitetsdokument vurderer hvert produktdomæne og arkitekturlag og sporer mangler over tid.
Planer betragtes som førsteklasses artefakter. Midlertidige letvægtsplaner bruges til små ændringer, mens komplekst arbejde registreres i eksekveringsplaner(åbner i et nyt vindue) med fremdrifts- og beslutningslogge, der tjekkes ind i lageret. Aktive planer, fuldførte planer og kendt teknisk gæld er alle versionsstyrede og placeres samme sted, så agenter kan arbejde uden at være afhængige af ekstern kontekst.
Dette muliggør progressiv afsløring: agenter starter med et lille, stabilt indgangspunkt og lærer, hvor de skal lede næste gang, i stedet for at blive overvældet fra starten.
Vi håndhæver dette mekanisk. Dedikerede linters og CI-jobs validerer, at vidensbasen er opdateret, krydsforbundet og struktureret korrekt. En tilbagevendende “doc-gardening”-agent scanner efter forældet eller forældet dokumentation, der ikke afspejler den reelle kodeadfærd, og åbner fix-up pull requests.
Efterhånden som kodebasen udviklede sig, skulle Codex' ramme for designbeslutninger også udvikle sig.
Fordi lageret er fuldstændigt agent-genereret, er det først og fremmest optimeret til Codex' læselighed. På samme måde som teams sigter mod at forbedre navigerbarheden i deres kode for nye ingeniøransættelser, var vores menneskelige ingeniørers mål at gøre det muligt for en agent at ræsonnere om hele forretningsdomænet direkte fra selve lageret.
Fra agentens synspunkt eksisterer alt, hvad den ikke kan tilgå i kontekst, mens den kører, reelt ikke. Viden, der findes i Google Docs, chattråde eller i menneskers hoveder, er ikke tilgængelig for systemet. Lokal-lager, versionerede artefakter (f.eks. kode, markdown, skemaer, eksekverbare planer) er alt, hvad den kan se.

Vi lærte, at vi med tiden var nødt til at skubbe mere og mere kontekst ind i repoet. Og hvad var den Slack-diskussion, der fik teamet til at blive enige om et arkitekturmønster? Hvis det ikke er synligt for agenten, er det ulæseligt på samme måde, som det ville være ukendt for en nyansat, der starter tre måneder senere.
At give Codex mere kontekst betyder at organisere og synliggøre de rigtige oplysninger, så agenten kan ræsonnere over dem, i stedet for at overvælde den med ad-hoc-instruktioner. På samme måde som man ville onboarde en ny holdkammerat i produktprincipper, ingeniørnormer og teamkultur (inklusive emoji-præferencer), fører det at give agenten disse oplysninger til et bedre afstemt output.
Denne formulering afklarede mange afvejninger. Vi foretrak afhængigheder og abstraktioner, der kunne internaliseres fuldt ud og ræsonneres om internt i repoet. Teknologier, der ofte beskrives som “kedelige”, har en tendens til at være lettere for agenter at modellere på grund af komponerbarhed, API-stabilitet og repræsentation i træningssættet. I nogle tilfælde var det billigere at lade agenten genimplementere delmængder af funktionalitet end at arbejde uden om uigennemsigtig opstrøms-adfærd fra offentlige biblioteker. For eksempel i stedet for at hente en generisk p-limit-lignende pakke, implementerede vi vores egen map-with-concurrency-hjælper: den er tæt integreret med vores OpenTelemetry-instrumentering, har 100 % testdækning og opfører sig præcis som vores runtime forventer.
At trække mere af systemet ind i en form, som agenten kan inspicere, validere og ændre direkte, øger indflydelsen – ikke kun for Codex, men også for andre agenter (f.eks. Aardvark), der også arbejder på kodebasen.
Dokumentation alene holder ikke en fuldt agent-genereret kodebase sammenhængende. Ved at håndhæve invarianter og ikke micromanage implementeringer, lader vi agenterne levere hurtigt uden at underminere fundamentet. For eksempel kræver vi, at Codex parser datastrukturer ved grænsen(åbner i et nyt vindue), men vi foreskriver ikke, hvordan det sker (modellen ser ud til at kunne lide Zod, men vi specificerede ikke det specifikke bibliotek).
Agenter er mest effektive i miljøer med strenge grænser og forudsigelig struktur(åbner i et nyt vindue), så vi byggede applikationen omkring en stiv arkitektonisk model. Hvert forretningsdomæne er opdelt i et fast sæt lag med strengt validerede afhængighedsretninger og et begrænset sæt tilladte kanter. Disse begrænsninger håndhæves mekanisk via brugerdefinerede linters (selvfølgelig Codex-genererede!) og strukturelle tests.
Diagrammet nedenfor viser reglen: inden for hvert forretningsdomæne (f.eks. App-indstillinger), kan kode kun afhænge af "fremad" gennem et fast sæt lag (Typer → Konfiguration → Repo → Tjeneste → Kørselstid → Brugergrænseflade). Tværgående hensyn (auth, connectors, telemetry, feature flags) kommer ind gennem en enkelt eksplicit grænseflade: Udbydere. Alt andet er forbudt og håndhæves mekanisk.

Det er den slags arkitektur, man normalt udsætter, indtil man har hundredvis af ingeniører. Med kodningsagenter er det en tidlig forudsætning: begrænsningerne er det, der muliggør hastighed uden forfald eller arkitektonisk afvigelse.
I praksis håndhæver vi disse regler med brugerdefinerede linters og strukturelle tests samt et lille sæt “smagsinvarianter”. For eksempel håndhæver vi statisk struktureret logføring, navngivningskonventioner for skemaer og typer, filstørrelsesgrænser og platformspecifikke pålidelighedskrav med brugerdefinerede lints. Eftersom lint-reglerne er brugerdefinerede, skriver vi fejlmeddelelserne for at kunne injicere afhjælpningsinstruktioner i agentens kontekst.
I en menneskefokuseret arbejdsgang kan disse regler føles pedantiske eller begrænsende. Med agenter bliver de multiplikatorer: når de først er kodet, anvendes de overalt på én gang.
Samtidig er vi klare omkring, hvor begrænsninger er vigtige, og hvor de ikke er. Det minder om at lede en stor organisation inden for ingeniørplatforme: håndhæv grænser centralt, tillad autonomi lokalt. Man er meget opmærksom på grænser, korrekthed og reproducerbarhed. Inden for disse grænser gives teams – eller agenter – betydelig frihed i, hvordan løsninger udtrykkes.
Den resulterende kode stemmer ikke altid overens med menneskelige stilistiske præferencer, og det er helt fint. Så længe outputtet er korrekt, vedligeholdelsesvenligt og læseligt for fremtidige agentkørsler, lever det op til kravene.
Menneskelig smag føres kontinuerligt tilbage i systemet. Kommentarer til gennemgang, refaktorering af pull requests og brugervendte fejl registreres som dokumentationsopdateringer eller kodes direkte i værktøjerne. Når dokumentationen ikke er tilstrækkelig, omsætter vi reglen til kode
Efterhånden som Codex' gennemløb blev øget, blev mange konventionelle ingeniørnormer kontraproduktive.
Lageret opererer med minimale blokerende merge-gates. Pull requests er kortvarige. Testflager håndteres ofte med opfølgende kørsler i stedet for at blokere fremskridt på ubestemt tid. I et system, hvor agent-gennemløb langt overstiger menneskelig årvågenhed, er rettelser billige, og ventetid er dyr.
Dette ville være uansvarligt i et miljø med lavt gennemløb. Her er det ofte den rigtige afvejning.
Når vi siger, at kodebasen er genereret af Codex-agenter, mener vi alt i kodebasen.
Agenter producerer:
- Produktkode og test
- CI-konfiguration og release-værktøjer
- Interne udviklerværktøjer
- Dokumentation og designhistorie
- Evaluerings-harness
- Gennemse kommentarer og svar
- Scripts, der administrerer selve lageret
- Definitionsfiler til produktionskontrolpanel
Mennesker forbliver altid en del af processen, men arbejder på et andet abstraktionslag end tidligere. Vi prioriterer arbejdet, omsætter brugerfeedback til acceptkriterier og validerer resultater. Når agenten har problemer, behandler vi det som et signal: Identificer, hvad der mangler – værktøjer, beskyttelsesrækværk, dokumentation – og send det tilbage til arkivet ved altid at lade Codex selv skrive rettelsen.
Agenter bruger vores standardudviklingsværktøjer direkte. De henter feedback fra gennemgang, svarer inline, skubber opdateringer og squasher og merger ofte deres egne pull requests.
Efterhånden som mere af udviklingsloopet blev kodet direkte ind i systemet (test, validering, gennemgang, feedbackhåndtering og gendannelse) har lageret for nylig passeret en meningsfuld tærskel, hvor Codex kan drive en ny funktion fra start til slut.
Med en enkelt prompt kan agenten nu:
- Validere den nuværende tilstand af kodebasen
- Genskabe en rapporteret fejl
- Optage en video, der demonstrerer fejlen
- Implementere en rettelse
- Validere rettelsen ved at køre applikationen
- Optage en anden video, der demonstrerer opløsningen
- Åbne en pull request
- Besvare agent- og menneskelig feedback
- Opdage og afhjælpe buildfejl
- Kun eskalere til et menneske, når der kræves dømmekraft
- Sammenflette ændringen
Denne adfærd afhænger i høj grad af den specifikke struktur og de værktøjer, der bruges i dette lager, og bør ikke antages at kunne generaliseres uden en tilsvarende investering, i hvert fald ikke endnu.
Fuld agent autonomi introducerer også nye problemer. Codex replikerer mønstre, der allerede findes i arkivet – selv ujævne eller suboptimale mønstre. Over tid fører dette uundgåeligt til afdrift.
Indledningsvis håndterede mennesker dette manuelt. Vores team plejede at bruge hver fredag (20 % af ugen) på at rydde op i “AI-rod.” Ikke overraskende kunne det ikke skaleres.
I stedet begyndte vi at indkode det, vi kalder "gyldne principper", direkte i lageret og oprettede en tilbagevendende oprydningsproces. Disse principper er holdningsprægede, mekaniske regler, der sikrer, at kodebasen forbliver læsbar og ensartet til fremtidige agentkørsler. For eksempel: (1) vi foretrækker delte hjælpepakker frem for håndlavede hjælpere for at holde invarianter centraliseret, og (2) vi undersøger ikke data "YOLO-style". I stedet validerer vi grænser eller bruger typede SDK’er, så agenten ikke ved et uheld kan bygge videre på gættede strukturer. Med en regelmæssig kadence har vi et sæt baggrundsopgaver i Codex, der scanner efter afvigelser, opdaterer kvalitetsgrader og åbner målrettede refaktorerings-pull requests. De fleste af disse kan gennemgås på under et minut og flettes automatisk.
Dette fungerer som 'affaldsindsamling'. Teknisk gæld er som et lån med høj rente: det er næsten altid bedre at betale det ned løbende i små bidder end at lade det vokse med renters rente og håndtere det i smertefulde ryk. Menneskelig smag fanges én gang og håndhæves derefter kontinuerligt på hver kodelinje. Dette giver os også mulighed for at opdage og løse dårlige mønstre dagligt, i stedet for at lade dem sprede sig i kodebasen i dage eller uger.
Denne strategi har indtil nu fungeret godt frem til intern lancering og ibrugtagning hos OpenAI. At udvikle et ægte produkt til virkelige brugere hjalp med at forankre vores investeringer i virkeligheden og vejlede os mod langsigtet vedligeholdelse.
Hvad vi endnu ikke ved, er, hvordan arkitektonisk sammenhæng udvikler sig over årene i et fuldt agent-genereret system. Vi lærer stadig, hvor menneskelig dømmekraft giver mest indflydelse, og hvordan vi kan kode den, så den forstærkes. Vi ved heller ikke, hvordan dette system vil udvikle sig, efterhånden som modellerne fortsætter med at blive mere kapable over tid.
Det er blevet klart, at det stadig kræver disciplin at bygge software, men disciplinen viser sig mere i strukturen end i selve koden. Værktøjerne, abstraktionerne og feedback-loopene, der holder kodebasen sammenhængende, bliver stadig vigtigere.
Vores mest udfordrende opgaver fokuserer nu på at designe miljøer, feedbacksløjfer og kontrolsystemer, der hjælper agenter med at opnå vores mål: at bygge og vedligeholde kompleks, pålidelig software i stor skala.
Efterhånden som agenter som Codex overtager større dele af softwarelivscyklussen, vil disse spørgsmål få endnu større betydning. Vi håber, at ved at dele nogle af vores tidlige erfaringer kan hjælpe dig med at overveje, hvor du skal investere din indsats, så du selv kan bygge videre.


