AI-systemen meta-engineeren: van traces naar beter geheugen
Automatische vertaling
Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.
Dit artikel opent Meta-Engineering AI Systems, een zesdelige gids voor closed-loop AI engineering: agents inzetten om failures te onderzoeken, wijzigingen te testen en de resultaten te gebruiken om AI-systemen te verbeteren.
Het gedrag van een AI-applicatie hangt van meer af dan alleen het model. Prompts, opgehaalde informatie, opgeslagen memory, tools en application code beïnvloeden allemaal wat er gebeurt. Wanneer een antwoord fout is, kunnen verschillende wijzigingen plausibel lijken. Het engineeringprobleem is bepalen welke wijziging helpt, wat die kost en wat die nog meer breekt.
Ik gebruik meta-engineering hier voor het ontwerpen van het verbeterproces zelf: welk bewijs de agent ziet, wat hij mag wijzigen, hoe we zijn voorstellen testen en wie beslist of we ze overnemen. Closed-loop beschrijft hoe dat proces leert van zijn experimenten. Elk resultaat bepaalt mede wat we daarna proberen of gebruiken, ook wanneer een voorgestelde wijziging faalt.
We kunnen dat werk stapsgewijs automatiseren. Een persoon kan de exacte wijzigingen specificeren die getest moeten worden, een set toegestane alternatieven voor een search-algorithm definiëren of de volgende proposal delegeren aan een LLM agent. De runner test elke candidate en bewaart het bewijs voor de volgende beslissing. Deze serie richt zich op het opnemen van agents in dat proces, terwijl execution, evaluation en adoption onder expliciete controle blijven.
De vraag die door alle zes delen loopt, is hoeveel van dit werk we aan een agent kunnen delegeren zonder dat het bewijs en de beslissing om een wijziging over te nemen hun betrouwbaarheid verliezen. We beginnen met het in kaart brengen van het volledige systeem en bouwen daarna een kleine werkende versie rond agent memory.
Wat de loop sluit
Er zijn twee verschillende loops die we in beeld moeten houden. Binnen een agent application kiest de runtime loop een actie, roept een tool aan, observeert het resultaat en gaat verder met de huidige taak van de gebruiker. De improvement loop werkt over meerdere versies van die applicatie heen. Die onderzoekt gedrag uit voltooide runs en test wijzigingen die latere runs moeten verbeteren.
De improvement loop begint met evidence: een fout antwoord, een ongewenste state change, excessive cost of een andere observeerbare failure. Een trace legt de stappen achter die uitkomst vast. De proposer kiest een candidate: een specifieke versie van een wijziging. Een runner voert de candidate uit op gedefinieerde taken en een evaluator controleert het resulterende gedrag tegen de requirements. In het live experiment van dit artikel is een LLM agent de proposer:
Evaluation informeert een beslissing; ze autoriseert zichzelf niet. Iemand moet beslissen of de gemeten benefit het overnemen van de wijziging rechtvaardigt, inclusief de effecten op cost, permissions en ander vereist gedrag. In deze serie beginnen we met een human reviewer. De proposer kan een wijziging voorstellen, maar kan de checks niet herschrijven, zijn eigen budget niet verhogen en zichzelf geen approval geven.
Er zijn twee return paths. De experiment history voedt latere proposals, ook wanneer een candidate wordt afgewezen. Als een candidate wordt goedgekeurd en overgenomen, levert het gedrag ervan nieuwe evidence uit gebruik. Een wijziging reversibel houden is belangrijk wanneer die evidence de oorspronkelijke experimentuitkomst tegenspreekt. Een score registreren is maar één stap; de loop is pas gesloten wanneer de evidence verandert wat we daarna proberen of gebruiken.
Het te verbeteren onderdeel is de target. Dat kan een memory policy, een retrieval pipeline, tool-selection-code of het programma zijn dat de context voor een model samenstelt. Model training is een andere mogelijke interventie. De loop kan met vaste model weights werken: de agent kan het omringende programma verbeteren zonder een model te trainen. Deze eerste demo bevat al de outer LLM agent. In latere delen versterken we de evaluator en testen we of agentic search de cost waard is ten opzichte van eenvoudigere methoden.
Kies hoeveel van de search je delegeert
Stel dat je al weet wat je wilt proberen: twee models vergelijken in een extraction-stap of memory thresholds van 0.6, 0.7 en 0.8 testen. Je kunt die keuzes zelf aanleveren en execution, scoring en reporting automatiseren. Na het lezen van de resultaten kies je het volgende experiment. De feedback loop werkt ook al heeft het systeem de candidates niet zelf bedacht.
Ik gebruik vier werkmodi om die verdeling zichtbaar te maken. De figuur toont één manier om steeds meer experimentdesign te delegeren: begin met exacte modelkeuzes, laat het systeem settings en goedgekeurde components doorzoeken of vraag een agent failures te onderzoeken en het volgende experiment te kiezen. De mens specificeert minder van elke poging, maar stelt nog steeds de regels voor de search vast.
De modenames beschrijven praktische arrangementen voor deze serie, geen industriestandaard voor autonomy levels. Wat mag veranderen en wie de wijziging kiest, zijn afzonderlijke beslissingen. Optuna’s search-space examples combineren modelkeuze met parameter ranges. Scikit-learn’s pipeline search vergelijkt alternatieve components via gewone grid search. Een component vervangen maakt het proces dus op zichzelf niet agentic. De breedtes in de figuur illustreren de werkverdeling in deze voorbeelden; ze zijn geen gemeten aandelen van control of effort.
Agent-led investigation beschrijft hoe de volgende poging wordt gekozen. De agent leest failures en eerdere resultaten, stelt een wijziging voor en past zich na de test aan. Dit volgt het onderscheid in Anthropic’s workflow and agent patterns: een predefined process kan execution automatiseren, terwijl een agent zijn volgende stappen vanuit feedback aanstuurt. Hybrid methods zijn ook mogelijk: DSPy’s MIPROv2 gebruikt een model om instructions voor te stellen en Bayesian optimization om combinaties daarvan te doorzoeken. Een fixed model comparison heeft geen LLM proposer nodig; de resultaten komen in de feedback loop terecht wanneer ze het volgende experiment of de volgende system version sturen.
Permissions voor proposal, execution en adoption blijven gescheiden. Een agent kan vóór elke run een wijziging ter approval opstellen of toegestane wijzigingen unattended testen terwijl een persoon adoption beoordeelt. Een goedgekeurde componentlijst heeft nog steeds compatible implementations nodig; permission om een adapter te selecteren omvat niet de permission om er een te schrijven. In elke mode blijft de agent binnen de toegestane wijzigingen, vaste checks en het budget en kan hij zichzelf geen deployment approval geven. Meer werk delegeren laat bovendien ruimte voor supervision: Anthropic’s study of deployed agents beschrijft hoe users verschuiven van het goedkeuren van individuele acties naar monitoren en interveniëren.
Alle modes kunnen dezelfde experiment ledger gebruiken: een record van elke attempted change. Bewaar de candidate en diens parent, de exacte wijziging en wie die heeft aangeleverd, de versies van test en environment, het resultaat, de cost en elke failure of rejection. Die history stelt een human in staat de volgende proposal aan een agent te geven — of die terug te nemen — zonder de evidence te verliezen. Scores uit verschillende testversies moeten nog steeds van elkaar worden onderscheiden.
Deze demo combineert configuration search met agent-led investigation. We definiëren vijf settings, de tests, het budget en de selection rule. De agent kiest values en de volgende hypothesis op basis van feedback; Python voert de tests automatisch uit. Human release review blijft gescheiden. De repository accepteert ook een candidate JSON supplied by a person via lab evaluate. Model sweeps, component adapters en door agents geschreven code zijn bredere designopties voor latere delen en geen geïmplementeerde modes van deze memory-demo.
Waarom dit nu onderzoeken
Het feedbackprincipe is bekende engineering. Het recente werk dat mij interesseert, plaatst coding agents binnen het investigation- en experimentproces. Het geeft ons concrete implementations om te onderzoeken, in plaats van ons te vragen aan te nemen dat autonomous improvement werkt.
Karpathy’s autoresearch specificeert een compact experiment: wijzig een training program, voer het uit onder een vaste training-time budget, inspecteer het validation result en registreer of de poging is behouden, discarded of gecrasht. De instructions scheiden het editable training file van de fixed evaluation code. Die scheiding maakt het voorgestelde werk en het succescriterium inspecteerbaar.
Meta-Harness, een preprint uit maart 2026, onderzoekt een andere target: de code die bepaalt welke informatie een LLM application opslaat, ophaalt en aan zijn model presenteert. De proposer kan via een filesystem eerdere candidates’ source, scores en execution traces inspecteren. Experiment history wordt werkmateriaal voor de volgende investigation.
Deze projecten motiveren de engineeringvraag van de serie: wat moet het omringende systeem doen zodra een agent wijzigingen kan onderzoeken en voorstellen om die experimenten nuttig te maken? Meer pogingen vormen op zichzelf geen bewijs voor betere beslissingen. Een zwakke evaluator kan een schadelijke wijziging belonen en een search process kan die zwakte herhaaldelijk uitbuiten. We testen de waarde van agentic proposals tegen eenvoudigere alternatieven in plaats van een voordeel aan te nemen.
Hoe de zes delen één systeem opbouwen
De artikelen ontwikkelen samen één companion project. Elk deel neemt een vraag over die door het vorige experiment openbleef en voegt het mechanisme toe dat nodig is om die te onderzoeken.
| Deel | Vraag | Wat het aan hetzelfde systeem toevoegt |
|---|---|---|
| 1. From traces to better memory | Kunnen we een failure omzetten in een reviewable improvement? | Een memory tool, een LLM proposer, bounded experiments, feedback en retained evidence. |
| 2. Make it scorable | Herkent de evaluator useful changes, inclusief schijnbare wins die harm veroorzaken? | Stronger evaluation, deliberate false wins en checks op wat de scores aantonen. |
| 3. The improvement harness | Welke onderdelen kunnen we hergebruiken over targets en working modes heen? | Gedeelde execution, history en permissions voor human, classical en LLM proposers. |
| 4. Compare search strategies | Hoeveel proposal work is het waard om aan een agent te delegeren? | Vergelijkingen met human en classical search onder matched budgets en allowed changes. |
| 5. Assured improvement | Welke evidence is voldoende om een apparent winner over te nemen? | Deeper adversarial testing, staged adoption en rollback controls. |
| 6. From history to training data | Kunnen reviewed experiments een learned component verbeteren? | Een klein verifier- of policy-training-experiment, getest tegen eenvoudigere repairs. |
Privacy checks en human review horen in de eerste versie. Deel 5 versterkt die bescherming naarmate de proposer meer capabilities krijgt. Deel 6 onderzoekt eveneens een mogelijk gebruik van de verzamelde evidence; elk eerder deel moet nuttig blijven zonder een nieuw model te trainen.
Geef de outer agent een kleine, inspecteerbare target
Stel je een assistant voor die Ada’s accountgegevens onthoudt. Op 1 januari leert hij dat ze in Berlijn woont. Op 3 januari leert hij dat ze per 10 januari naar Parijs verhuist. Wanneer je op 5 januari naar haar stad vraagt, antwoordt hij Parijs.
De memory bevat beide facts. De retrieval rule geeft de recentst ontvangen fact de voorkeur zonder te controleren wanneer die geldig wordt. Dat is een concrete failure die een improvement agent kan onderzoeken.
De target is bewust alleen een memory tool, geen complete assistant. De tool ontvangt prepared facts, slaat ze op of weigert ze en haalt een value op voor een vraag. De writer, date handling, retrieval en answer selection zijn gewone Python. Conversation extraction en natural-language answer generation laten we buiten dit experiment, zodat we kunnen vaststellen wat een rule change precies heeft gedaan.
De LLM zit in de outer loop van het Python-experiment. De agent ontvangt testresultaten, beslist welke settings moeten veranderen en krijgt het volgende resultaat terug. De recorded campaigns gebruiken een echt model om die wijzigingen te kiezen.
Door deze verdeling kunnen we de engineeringloop testen zonder een tweede bron van modelgedrag binnen de memory tool te introduceren. In een grotere application zouden beide loops models kunnen gebruiken. Hier volstaat één LLM om het improvement process agentic te maken. Een andere LLM kan dezelfde proposer role vervullen; diens proposals moeten hetzelfde schema volgen en dezelfde checks doorstaan.
Inspecteer het experiment
De companion repository op GitHub bevat de outer agent, de memory tool, tests en compacte reports van drie echte LLM-campagnes. Complete requests, responses en traces zijn beschikbaar in een checksummed evidence archive. Het experiment report volgt de voorgestelde wijzigingen, hun gemeten resultaten en elke beslissing om te stoppen. Later in het artikel gebruiken we de repository om een nieuwe campaign uit te voeren.
Begrijp eerst één test voordat je de score leest
Een scenario is één complete test story. Een event is één actie die naar de memory tool wordt gestuurd: write, query of delete. Het future-move-scenario heeft vier events:
- Save
city = Berlin, effective January 1. - Save
city = Paris, received January 3 but effective January 10. - Ask for the city on January 5. Expect Berlin.
- Ask for the city on January 12. Expect Paris.
De inputs zijn al gestructureerd. De Paris-fact identificeert bijvoorbeeld de owner (north workspace, user ada), subject (account), property (city), value (Paris) en effective date. De strings Berlin en Paris komen uit de testdata, niet uit een model dat memories uit een conversation genereert.
Confidence is een aangeleverde score die bepaalt of een proposed fact wordt opgeslagen. De writer vergelijkt die met min_confidence. Een delivery = courier-proposal met score 0.4 wordt bij de baseline threshold van 0.7 afgewezen, maar bij een threshold van 0.2 opgeslagen. De test author levert de score aan; het is geen gemeten probability dat de proposal correct is. We evalueren hoe de storage rule met die scores omgaat, niet of een model ze betrouwbaar kan schatten.
Elk scenario begint met een lege Python-list met memory records. Accepted updates sluiten de validity period van de vorige value en voegen een nieuw record toe. Na de twee city writes beschrijven de records:
| Value | Received | Valid from | Valid until |
|---|---|---|---|
| Berlin | January 1 | January 1 | January 10, excluded |
| Paris | January 3 | January 10 | No end date |
De answer function retourneert het eerste retrieved record dat overeenkomt met de gevraagde property. De evaluator vergelijkt die value met het expected answer. Een compleet scenario slaagt alleen wanneer elk answer correct is en elke toepasselijke data-rule-check slaagt. Deletion, owner isolation en prohibited writes hebben naast answer quality expliciete checks.
De tests leveren owner IDs direct aan; deze demo heeft geen authentication system. Een input die expliciet als instruction is gelabeld afwijzen, toont ook niet aan dat instructions worden gedetecteerd die in gewone tekst verborgen zijn.
Geef memory ook een schema
De facts hebben hun eigen rules nodig. Ik gebruik Schema-Guided Agent Memory (SGAM) voor het pattern waarin schemas de opgeslagen state en diens lifecycle bepalen. Hier demonstreren we er een klein onderdeel van: typed facts, ownership, source references, validity intervals en deletion. Het latere SGR schema bepaalt wat de outer agent mag voorstellen; dit memory schema bepaalt wat de tool mag opslaan.
Het Paris-record na de tweede write bevat:
{
"tenant": "north",
"user": "ada",
"entity": "account",
"key": "city",
"value": "Paris",
"confidence": 0.95,
"source": "user",
"valid_from": "2026-01-10",
"schema_version": 1,
"memory_type": "fact",
"id": "m002",
"source_event_id": "future-move:event-2",
"observed_at": "2026-01-03",
"valid_to": null,
"supersedes_memory_id": "m001"
}
source_event_id verwijst naar het event dat Paris heeft aangeleverd. supersedes_memory_id linkt Paris aan het Berlin-record, m001. schema_version: 1 identificeert het recordformat; het betekent niet dat het programma oude data automatisch kan migreren.
MemoryRecord en Memory.write() handhaven dat format. Ontbrekende source references, ongeldige dates en malformed fields worden afgewezen voordat stored history verandert. Een closed interval moet na het begin eindigen. Berlin kan op 10 januari eindigen terwijl Paris die dag begint; geen van beide records heeft een empty interval.
Stel dat de volgende write zegt Rome, ook effective January 10. De writer wijst dat conflict af en laat Paris ongewijzigd. Een tweede Paris-fact voor dezelfde datum gebruikt simpelweg opnieuw het record. Een update met een eerdere effective date wordt eveneens afgewezen: deze kleine writer reconstrueert geen late-arriving history. Dit zijn fixed policies die de outer agent niet kan wijzigen. Zijn deduplicate-setting bepaalt hoeveel herhaalde confirmations met een latere effective date worden uitgevoerd.
De baseline negeert bij het lezen nog steeds subject- en date-filters. Hij slaat geldige records op, maar kan de verkeerde selecteren. Dat is de fault die we de agent geven om te repareren. Owner isolation geldt voor elke configuration en deletion verwijdert alle versions van de gevraagde property binnen de subject van die owner.
Dit is een in-memory demonstration van die SGAM rules. Er is geen durable database, retention service of migration system. Afzonderlijke writer regression tests controleren rejected writes en interval boundaries; ze zijn geen extra scenarios in de 20-story campaign score.
Laat de agent een wijziging kiezen
Een campaign is één poging om de oorspronkelijke configuration te verbeteren, met fresh agent history als startpunt. Een iteration is één call waarin de agent een wijziging voorstelt of besluit te stoppen. De volgende iteration ontvangt feedback van eerdere iterations.
De campaign begint met alleen de baseline. Die slaagt voor 13 van 20 scenarios. Vervolgens geven we de agent:
- de huidige settings en hun betekenissen;
- de measurements van de baseline;
- traces van failing scenarios, rejected writes en duplicate confirmations;
- de wijzigingen die hij mag voorstellen;
- eerdere proposals en hun resultaten, als die er zijn.
De eerste request bevat geen kant-en-klare improved configurations. De repository bevat ook vier handmatig voorbereide configurations om memory mechanics uit te leggen, maar de live agent begint niet met die antwoorden.
De agent kan vijf settings in de bestaande tool wijzigen:
| Setting | Wat een wijziging doet |
|---|---|
min_confidence | Wijzigt de minimum supplied score die nodig is om een fact op te slaan. |
filter_entity | Beperkt retrieval tot de gevraagde subject, zoals home in plaats van work. |
time_aware | Beperkt retrieval tot facts die op de gevraagde datum geldig zijn. |
deduplicate | Gebruikt een identieke active fact opnieuw in plaats van nog een confirmation op te slaan. |
top_k | Bepaalt hoeveel records worden geselecteerd voordat de answer context wordt packed. |
Een proposal mag maximaal twee settings wijzigen. Numeric values hebben bounds: confidence van 0 tot 1 en top_k van 1 tot 8. Het contract registreert de toegestane configuration changes van de tool; het agent schema en de validator voegen de proposal rules toe.
De agent heeft in dit proces geen shell- of filesystem-tools. Hij kan Python, expected answers, owner isolation, deletion behavior, het memory schema, conflict handling, scoring, budgets of release authority niet wijzigen. Zijn output is data die Python kan accepteren of afwijzen. Dit is een klein configuration experiment, geen sandbox voor arbitrary code die door een agent wordt geschreven.
Maak elke proposal tot een SGR decision record
Ik gebruik Schema-Guided Reasoning om de beslissing inspecteerbaar te maken. Elke modelresponse heeft dezelfde fields:
| Field | Wat de reader moet kunnen inspecteren |
|---|---|
observations | Welke supplied scenario en event ondersteunen de voorgestelde wijziging? |
hypothesis | Welke rule lijkt het probleem te veroorzaken? |
predicted_effect | Wat zou moeten verbeteren wanneer we de wijziging testen? |
action | Stelt de agent een wijziging voor of stopt hij? |
patch | Welke permitted settings moeten veranderen? |
De OpenAI Responses request gebruikt een strict JSON Schema dat uit Pydantic models wordt gegenereerd. Objects weigeren extra fields en elk patch field is required maar mag null zijn, wat betekent: “laat deze setting ongewijzigd.” Structured Outputs beperkt de response shape. Python controleert nog steeds of references bestaan, values toegestaan zijn en de voorgestelde configuration niet al is getest.
Het schema bewijst de hypothesis niet en maakt de interne reasoning van het model niet zichtbaar. Dit zijn beknopte decision records die we tegen evidence kunnen controleren.
In de eerste recorded iteration identificeerde de agent cross-subject retrieval en facts die buiten hun validity interval werden teruggegeven. Zijn actual response stelde deze patch voor:
{
"min_confidence": null,
"filter_entity": true,
"time_aware": true,
"deduplicate": null,
"top_k": null
}
Deze twee settings werden door het model gekozen. De runner leverde de parent ID aan en kende de candidate ID toe; het model kon de wijziging niet omleiden naar een willekeurige parent of file.
Volg de wijziging door Python
Zowel de baseline als de nieuwe configuration slaan dezelfde Berlin- en Paris-records op. De voorgestelde wijziging bepaalt welke records retrieval mag overwegen.
In Memory.query() activeren deze switches twee filters:
if self.config.filter_entity:
eligible = [r for r in eligible if r["entity"] == event["entity"]]
if self.config.time_aware:
eligible = [r for r in eligible if valid_at(r, event["as_of"])]
De validity check include de start date en sluit de end date uit:
def valid_at(item: dict, at: str) -> bool:
return item["valid_from"] <= at and (
item["valid_to"] is None or at < item["valid_to"]
)
De dates gebruiken YYYY-MM-DD, waardoor hun string order overeenkomt met hun calendar order. Voor de vraag van 5 januari wordt Paris uitgesloten omdat die fact op 10 januari geldig wordt. Berlin blijft beschikbaar. Voor de vraag van 12 januari is Paris geldig en Berlin historical.
Python voert de voorgestelde configuration uit op alle 20 stories. Deze eerste wijziging verhoogt success van 13/20 naar 19/20, waarbij alle geïmplementeerde hard checks slagen. De wijziging activeert twee filters tegelijk, dus de suite-wide gain meet hun gecombineerde effect. De city trace identificeert wat de date filter in dit specifieke geval deed.
De runner selecteert deze configuration als parent voor het volgende experiment. Die selectie betekent niet dat de configuration wordt gedeployed. Het model krijgt in de volgende request het gemeten resultaat, de geselecteerde settings en de resterende evidence terug.
De volgende beslissing moet het resultaat gebruiken
Hier is de complete eerste campaign. Elke row is een echte modelresponse, geen vooraf geschreven stap in een demonstration script:
| Iteration | Wat de agent voorstelde | Wat Python deed | Huidig beste resultaat |
|---|---|---|---|
| 1 | Subject- en date-filters activeren | Gevalideerd en getest; de improvement geselecteerd | 19/20 |
| 2 | Identieke confirmations dedupliceren | Getest; geselecteerd omdat storage daalde zonder slechtere answers | 19/20 |
| 3 | min_confidence verlagen van 0.7 naar 0.6 | Getest; geselecteerd omdat het laatste failing scenario slaagde | 20/20 |
| 4 | Stoppen | Stopbeslissing geregistreerd; geen verdere wijziging | 20/20 |
De tweede response verwees naar het duplicate-confirmation-scenario. Dat verhaal schrijft language = German drie keer. Deduplication houdt één record in plaats van drie over en behoudt het answer. Over de suite daalde het gemiddelde aantal stored records van 1.70 naar 1.60, terwijl success 19/20 bleef.
De derde proposal pakte een andere failure aan. Een useful language preference had een supplied confidence van 0.6, onder de huidige 0.7-threshold. Door de threshold naar 0.6 te verlagen, werd die fact toegelaten terwijl het uncertain courier proposal met score 0.4 nog steeds werd afgewezen. Success bereikte 20/20; het gemiddelde aantal stored records werd 1.65, omdat memory nu de extra useful fact behield.
Bij de vierde call koos de agent ervoor te stoppen: op basis van de supplied evidence had hij geen verdere onderbouwde wijziging voor te stellen. Dat is een modelbeslissing, geen bewijs dat de configuration globaal optimaal is.
De volgende request bevat de huidige results en eerdere decisions. Nadat de agent zag dat zijn retrieval fix hielp, ging hij verder met storage en write admission. De runner leverde die volgende patches of een vooraf geschreven sequence of steps niet aan.
De selection rule ligt vast: alle hard checks moeten slagen, complete-scenario success heeft de voorkeur en bij gelijke success hebben minder stored records de voorkeur. Een slechter resultaat laat de vorige parent intact. De tests oefenen die rejection path ook uit met een scripted regressing proposal; het was geen gemeten quality regression in deze drie live campaigns.
Een afzonderlijke development run bevat een echte validation rejection: de agent verwees naar agent-01, een candidate ID, alsof het een scenario was. De response voldeed aan het JSON schema, maar de reference identificeerde geen supplied event, waardoor Python die vóór evaluation afwees. De controller retourneert de rejected response en de specifieke validation error als feedback; offline tests controleren dat gedrag. De drie hieronder gerapporteerde campaigns hadden geen validation failures.
Herhaal de search campaign, niet de deterministische test
Dezelfde memory configuration en inputs produceren dezelfde answers. Die evaluation herhalen voegt geen evidence over answer quality toe. De runner controleert een nieuwe configuration één keer en hergebruikt verified parent results voor vergelijkingen.
De outer agent kan verschillende proposals kiezen, dus we voerden drie onafhankelijke campaigns uit. Elke campaign begon met dezelfde baseline van 13/20, kreeg fresh history en had maximaal vier model decisions. Geen enkele campaign ontving de discoveries van een vorige campaign.
| Campaign | Model decisions | Proposals evaluated | Proposals rejected before evaluation | Selected success | Waarom hij eindigde |
|---|---|---|---|---|---|
| 1 | 4 | 3 | 0 | 20/20 | Agent stopte |
| 2 | 4 | 3 | 0 | 20/20 | Agent stopte |
| 3 | 4 | 3 | 0 | 20/20 | Agent stopte |
Alle drie campaigns kozen dezelfde sequence: beide retrieval filters activeren, confirmations dedupliceren, de confidence threshold verlagen naar 0.6 en vervolgens stoppen.
Er waren 12 model calls: negen proposals die Python evalueerde, gevolgd door drie stop decisions. Elke campaign voerde de baseline plus drie nieuwe configurations uit op 20 stories: 80 memory-tool executions per campaign. De 20 stories bleven gedurende het hele experiment gelijk.
Alle drie selecteerden dezelfde final settings. Dit is een kleine observatie over één model, één prompt, één target en één public test suite. Het schat niet hoe betrouwbaar de optimizer onbekende systems zal verbeteren. Een stronger comparison hoort later in de serie thuis: repeated campaigns onder matched budgets, competing proposal methods en tests die de proposer niet kan inspecteren.
Lees quality en cost op het juiste niveau
Het experiment heeft twee verschillende costs. De memory tool uitvoeren gebruikt local CPU time en doet geen model calls. De outer proposer uitvoeren gebruikt input- en output-tokens. Een zero provider-cost field in een memory evaluation report beschrijft alleen de inner tool; het is niet de cost van de campaign.
Voor de recorded study op 11 september 2026 gebruikten we GPT-5.6 Luna (gpt-5.6-luna), reasoning effort low, het opgeslagen SGR schema en de instructions, en maximaal 4.096 output tokens per call. Het programma schakelde automatische SDK retries uit en stelde een request timeout van 60 seconden in. Exacte requests, returned model IDs, usage en call durations worden bewaard.
De token-based cost estimate voor de 12 model calls is USD 0.039177, tegenover een geconfigureerd budget van USD 0.50. De berekening gebruikt de gepubliceerde model rates, bevat de cache-write surcharge die in usage is gerapporteerd en negeert cache-read discounts. Het is een conservatieve schatting op basis van recorded usage, geen invoice. Hardware en development time vallen buiten dat bedrag.
Vóór elke call reserveert de runner een upper estimate op basis van bounded input size en het maximumaantal output tokens. Als het resterende budget die reservation niet kan dekken, stopt hij. Failed of interrupted calls blijven in het record; wanneer usage niet beschikbaar is, blijft het gereserveerde bedrag behouden in plaats van als nul te worden behandeld.
Voor answer quality betekent 20/20 dat elk answer en elke toepasselijke hard check slaagde op deze 20 prepared stories. Het betekent niet dat memory production-ready is. Alle stories zijn public development cases; selected traces en suite feedback zijn beschikbaar voor de proposer. Ze omvatten updates, historical questions, uncertainty, duplicates, distractors, owner separation, deletion en disallowed writes. De labels search, evaluation en adversarial structureren de oorspronkelijke suite; ze maken geen van deze cases tot een hidden test set.
Deze kleine suite ontleent ideeën aan LongMemEval, MemoryAgentBench, VehicleMemBench en GateMem. De inputs en scoring zijn hier van onszelf; de resultaten reproduceren die benchmarks niet.
Je kunt ook vier handmatig voorbereide configurations in de repository vergelijken. Ze illustreren waarom meer facts accepteren answers slechter kan maken en hoe storage kan verbeteren zonder hogere answer quality. Ze tonen ook de human-specified kant van dezelfde experiment machinery: de author levert de candidates aan en Python evalueert ze. Het zijn nuttige teaching comparisons, geen evidence dat agentic search beter presteert dan een competente human of een andere search method.
Voer een nieuwe agent campaign uit
Om de agent nieuwe proposals te laten kiezen, clone je de companion en download je de recorded evidence:
git clone --branch v0.2.2 --depth 1 https://github.com/slavadubrov/meta-engineering-ai-lab.git
cd meta-engineering-ai-lab
uv sync --frozen
uv run --frozen python scripts/fetch_evidence.py
uv run --frozen python -m lab verify artifacts/agent-study-03 --source
De download controleert SHA-256 en herstelt de volledige recordings onder artifacts/. Er worden geen model calls gedaan. Als je de evidence al hebt gedownload, sla je die stap over en voer je de verification command uit.
Sla een OPENAI_API_KEY op in een lokaal .env.local-bestand. De repository negeert dat bestand. Voer daarna uit:
uv run --frozen --env-file .env.local python -m lab campaign \
--live --campaigns 3 --iterations 4 --budget-usd 0.50 \
--output artifacts/my-agent-study
--live activeert provider calls expliciet. Een key in de environment maakt de offline memory commands of browser niet automatisch tot een live agent. --campaigns 3 maakt drie onafhankelijke agent histories aan; --iterations 4 beperkt het aantal decisions binnen elke history. Gebruik voor elke study een nieuwe output directory: bestaande evidence wordt nooit overschreven.
Open artifacts/my-agent-study/report.md voor de campaign outcomes en links naar elke request, response en Python evaluation. Vergelijk de voorgestelde wijzigingen met de hierboven recorded campaign: de agent kan anders kiezen, ook al zijn de memory tests deterministisch.
De README koppelt de code aan de commands. Het frozen campaign report en de archive checksum and example index stellen een reader in staat de evidence van dit artikel direct te inspecteren.
Houd experiment history gescheiden van user memory
De memory tool slaat Ada’s city en language op. De experiment history slaat op wat de agent zag, de voorgestelde patch, eventuele rejection, de resulterende measurements en welke configuration de volgende parent werd. Deze stores dienen verschillende doelen.
Elke iteration bewaart de exacte request met instructions en schema, de provider response, usage en timing, de validation outcome en elke completed evaluation. Failed proposals blijven zichtbaar. File hashes binden de opgeslagen evidence aan de implementation en inputs die voor het experiment zijn gebruikt.
Dit zijn synthetic facts, dus het public record kan volledige states behouden. Voor echte traces is een afzonderlijke retention policy nodig: een fact uit de memory tool verwijderen wist eerdere copies uit experiment logs of backups niet. De deletion test van de demo controleert de records en latere reads van de tool, niet erasure uit elke mogelijke store.
Wat het volgende artikel moet uitdagen
We hebben nu een agent binnen de improvement loop. Die stelt een wijziging voor, ontvangt een measured result, kiest de volgende wijziging en kan besluiten te stoppen. Invalid proposals volgen een aparte rejection path en blijven in het record. Zijn authority is beperkt tot configuration; testing en release review blijven afzonderlijke responsibilities.
Het volgende risk is de evaluator zelf. Als success beloont dat elke fact wordt behouden, kan de agent leren guesses te bewaren. Als een suite alleen naar de huidige city vraagt, kan die een wijziging missen die useful history vernietigt. Een capable proposer kan weak measurements efficiënter exploiteren.
Deel 2, Make It Scorable Before You Make It Autonomous, vraagt hoe we die measurements kunnen testen voordat we de proposer meer freedom geven. De 20/20 van de eerste campaign is het starting point voor die investigation.