---
title: agentNet, a postmortem on agentic code ownership
date: 2026-08-18
---

agentNet is an experimental framework that explores the idea of deploying persistent agents in a codebase as code owners.

## Inspiration

This idea emerged a while back while playing around with [ralph loops](https://www.youtube.com/watch?v=4Nna09dG_c0) (Shoutout @GeofreyHuntley). This was my first time truly getting my hands dirty with agents, and I was very excited to finally see something reminiscent of a traditional engineering principle in a field that at the time seemed to be so vibe-based: **context encapsulation**. Ralph loops were a very early implementation of what we now all know as "loop engineering", with a painfully simple harness: a checklist of tasks, an AGENTS.md file pointing at the checklist, and a bash loop that would spawn one agent after another. As naive as this sounds, context rot was one of the biggest bottlenecks when working with agents at the time, and the simple idea of having one agent with a fresh context window per task showed a dramatic improvement in output.

While this was happening I was coming fresh off of an [internship at Google](https://www.linkedin.com/posts/mfserna_webai-googleinterns-google-ugcPost-7361756749734817793-Ek-o/?utm_source=share&utm_medium=member_desktop&rcm=ACoAAEbDbtIB_oszzSIPqJp5cwtE2kGw0myQMVA), where I had just experienced the brilliance (and pain) of code ownership. Code ownership was astutely designed for a very practical purpose (given Google's monorepo), but to me, it also represented a more philosophical way to map domain expertise, or how we keep it encapsulated as humans. As model capabilities improved and people started experimenting with so-called "code factories" (fully autonomous coding pipelines), agentic code owners seemed like a reasonable next step.

## Hypothesis

Ultimately, agentNet is a bet that agents are still bottlenecked by context to a meaningful degree, and that the solution is organizational. Bigger context windows delay the problem but don't solve it: an agent that loads an entire repository loses precision, doesn't know where to act, and violates local conventions it never had the scoped understanding to learn. If that's true, then a network of persistent agents, each owning a bounded area deeply, and collaborating through explicit handoffs, should outperform any single agent with a bigger window.

Spoiler: it didn't, not in the form I framed it. But giving it a fair shot took building an indexer, a governance layer, a Kubernetes control plane, a proper benchmark harness, and more. This article goes through the whole arc: how agentNet works, how I measured it, what the numbers actually said, what doesn't work, and the parts where this idea still might have legs.

## Implementation

agentNet comprises three layers: a code graph, an ownership graph built on top of it, and a control plane that turns each ownership zone into a persistent agent. Everything downstream from there (routing, context assembly, builds, review) is a traversal of these structures.

![agentNet layer by layer: the code graph indexes files and symbols, the ownership graph clusters them into zones stacked into a tree, and the control plane deploys each zone as a long-lived agent on Kubernetes](/agentnet/architecture-layers.png)

### A graph optimized for context grouping

The first thing agentNet does with a repository is index it into a code graph. Every file gets parsed with tree-sitter, and the graph collects nodes for the repo (directories, modules, files, and symbols) connected by contains, defines, imports, calls, and references edges. If an embedding provider is available, an extra pass adds similar_to edges between files whose embedded signatures land close together.

This is not a compiler-grade symbol resolver. Import and call targets are stored as local string symbols instead of resolved cross-file references; that would be too expensive and past the point of this experiment. The graph doesn't care to answer where functions are defined; it exists to represent which files should belong together in one code owner's "head".

The whole grouping mechanism boils down to a handful of weights:

```ts
// how related are two files?
const symbol =
  jaccard(a.imports, b.imports) * 0.5 +   // shared imports
  jaccard(a.calls,   b.calls)   * 0.35 +  // shared function calls
  jaccard(a.defs,    b.defs)    * 0.15;   // similarly named definitions

const relation =
  directoryProximity * 0.45 +  // how close they live in the file tree
  symbol             * 0.3 +   // the symbol overlap above
  embeddingSim       * 0.25;   // embedding similarity, when available

// growing a zone: seed from the most central file,
// pull in the closest neighbors until the owner's budget fills
for (const candidate of rankBy((f) => relationScore(seed, f))) {
  if (usedTokens + candidate.estimatedTokens > maxTokens) continue;
  zone.push(candidate);
  usedTokens += candidate.estimatedTokens;
  if (usedTokens >= targetTokens) break; // ~30% of the context window
}
```

These weights are meant to optimize for grouping code related in context, which isn't necessarily the code that's nearest. Living in the same directory is still the strongest signal (we already organize repos by team in real life), but I decided importing the same things matters more than calling the same things, and embeddings get the smallest say. None of this is principled in the machine-learning sense, although I did do some light testing around the weights; there might be some alpha to gain here.

### Creating ownership areas

The governance layer breaks the graph into zones, each of which gets an agent. These agents that directly own code are called "leaves", and are grown greedily: we rank files by centrality (sum of relation scores), seed a cluster from the most central unassigned file, and keep pulling in the most related files until the cluster fills roughly 30% of the owner's context window. The cap is meant to keep the relevant code knowledge inside the model's [smart zone](https://www.aihero.dev/ai-coding-dictionary/smart-zone) while leaving some room to think.

Leaves then get grouped into bridge coordinators wherever their average pairwise relation clears a threshold, recursively, up to a root agent that sits over everything; you can think of these as your middle managers. Leaves own files, bridges own the relationships between their children and explicitly do not own files, the root owns routing.

Each zone also carries an "abstraction": a distilled statement of its interfaces, contracts, and invariants, derived heuristically from what its files define and import, plus conventions mined from the actual source at deploy time. This is the zone's institutional knowledge, some of what a new hire might learn in their first month on that team.

![An example ownership graph over fastify: a root that routes work, bridge coordinators that know how their leaves fit together, and leaves owning small clusters of files sized to a third of a context window](/agentnet/ownership-tree.png)

### Kontext as the control plane

Persistent owners create an operations problem before they create anything interesting: a few dozen "always on" agents need something that starts them, feeds them credentials, restarts them when they die, and records everything they're asked to do. I built that as its own project. [Kontext](https://www.kontext.run/) is a Kubernetes operator that treats agents as ordinary workloads, with two custom resources: Agent, the reusable definition (analogous to a Deployment), and AgentRun, one bounded, auditable execution (analogous to a Job). The point is that owners inherit a decade of production plumbing (scheduling, secrets, logs, budgets, restarts) instead of me rebuilding it by hand, badly. To be clear, Kontext is the control plane, not the brain: it ships a reference runtime, but agentNet brings its own image, and Kontext never learns what a "zone" or "code owner" is. It's completely independent and [open source](https://www.github.com/MFS-code/Kontext).

<blockquote class="twitter-tweet" data-theme="dark" data-conversation="none">
  <p lang="en" dir="ltr">My main project this summer has been kontext.run, an open source Kubernetes control plane for running AI agents. Today I&#39;m releasing the first alpha. Agents should run like production workloads, not fragile scripts. Here&#39;s a demo:</p>
  &mdash; Miguel Serna (@miguelfserna) <a href="https://x.com/miguelfserna/status/2079657007259259157">July 22, 2026</a>
</blockquote>

agentNet deploys every zone as a Service-mode Kontext Agent: always on, knowledge mounted from a ConfigMap, re-cast automatically if the pod dies (the replacement boots from stored knowledge, not the dead process's memory; the role survives, not the conversation). Work arrives as AgentRuns against the standing owner: route hops, context assembly, builds, reviews...

Admittedly, Kubernetes was not the obvious choice. A process supervisor and a SQLite file would have been simpler. But the mapping was clean (a standing owner is a Deployment, a bounded request is a Job), and I wanted to learn Kubernetes, so I thought this would be a good excuse to do it.

### The two build modes

When first pitching people on agentNet, my idea was to have it be this auxiliary "router" tool that is always there and helps an agent carry out a task by feeding it the relevant context. However, when trying to explain this, people always seemed to assume that the code owners would be the ones dividing up the work and writing their own code. This idea seemed equally plausible so I decided to implement it as well. Because of this, I ended up with two build modes:

Mode one: context-pack handoff. The owners don't write code at all. You bring your own working agent (Codex, Claude Code, whatever), and agentNet routes your task to the right zone and assembles a scoped context pack: relevant source code chunks with provenance, the zone's mined conventions, an explicit scope statement, and surrounding zones that might become relevant. The pack gets handed to your agent and agentNet steps out of the way.

Mode two: internal owner build. The owners produce the changes themselves. A request is routed down the tree to a target leaf, the coordinator collects a bounded file pack, and the owner returns a structured proposal: full post-change file contents plus rationale and caveats. The product then computes the unified diffs locally; I didn't want the models to emit diffs as that adds another failure point with unreliable diff generation when using cheap models. The proposal goes through an adversarial review by the coordinator before anything touches the repo.

Note that mode two is a single scoped proposal call. No tools, no iteration, no running the tests. That constraint is deliberate in order to make the ownership structure measurable (I'll expand on this in a bit), but it also came back to bite me.

![The two build modes side by side: context-pack handoff, where the zone writes a briefing and an outside agent implements it, and internal owner build, where the leaf drafts the change and the coordinator signs off or rejects](/agentnet/build-modes.png)

### Bonus cool things

A few pieces of engineering that don't fit the narrative but that I wanted to mention anyway.

- Routing is an LLM descent down the ownership tree where each zone's model picks among its own children with a confidence score, and any ambiguity (multiple children, low confidence) stops the descent at the coordinator rather than guessing deeper, so uncertainty degrades into a wider scope instead of a wrong one.

- Oversized build results get parked as artifacts and fetched out-of-band; I had never really dealt with Kubernetes object size limits.

- agentNet features an Electron desktop app that renders the ownership graph and lets you chat with individual owners, never important for the research but cool for demos.

## Measurement

At this point agentNet worked in the literal sense. I could point it at a repository, generate an ownership graph, deploy the owners, and route work through them. Of course, the whole value of the project was in finding out whether the ownership structure actually helped agents, so half the battle was measuring it.

### Freezing tasks

The main method I used to test agentNet was PR-replay. I would take a real merged PR from an upstream repo, check out its parent commit so the agents were working on the codebase before the fix, and prompt the agents with the linked issue text. Validation runs would test the outputs against the upstream PR itself, cherry-picked from the ground-truth patch.

![Task family 1, replaying a real fix: the clock rewinds to one commit before the fix landed, the agent gets the same bug report, and the human fix's tests judge the agent's patch](/agentnet/pr-replay.png)

For memorization insurance there's a second family, feature-by-analogy: implement X in place P the way it already exists in place Q of the same repo. These never happened upstream, so they can't be in anyone's training data, and the held-out tests were written and committed before any measured run. The full task list was hashed and frozen, instances split into dev and holdout sets, every record tagged with the agentNet git sha and harness sha, and control-arm results cached so iterating on agentNet never re-rolled the baselines.

![Task family 2, the feature by analogy: recreate a pattern that already exists in one place of the repo somewhere it has never existed, graded by held-out tests committed before the first scored run](/agentnet/task-freezing.png)

The task catalog pulled from real upstream repos across a few languages, mostly mid-size projects where tests run fast: fastify and vue for JS/TS, tokio for Rust, django and redis for the convention-heavy cases, hugo for Go, and xv6 as the small C teaching kernel where something like a syscall can touch six files. Larger repos like Kubernetes and TypeScript were in the catalog for localization stress tests; unfortunately, agentNet's indexer couldn't handle them yet, which meant every number in this article comes from the mid-size regime where a frontier agent's context window might not be that constrained.

### Ensuring fairness

The claim I was testing has to do with structure; however, as I mentioned before, agentNet's internal path is limited: a single proposal call, no tools, no iteration, no running the tests. Any other SOTA agent (cursor-agent in this case) would get an agentic loop, shell access, and the full repo. Which obviously doesn't make for a good comparison.

> So why not give agentNet its own full agentic loop?

While this might seem like an obvious move, doing such a thing would completely destroy our experiment. Comparing two agents with loops where one starts with more context is just "agent vs. agent with a head start": the head start will help; we don't need an experiment for this. Even worse, if the head start actually hurts the agent, the loop actively hides the thing I'm trying to measure: an agent that can grep, read files, and retry will go find whatever context the ownership structure failed to hand it, so a bad pack and a good pack will converge to the same score; we'd just be testing runtimes.

This is also the point where I want to address the external build mode introduced earlier (context-pack handoff mode), as you will not hear about it for the rest of the report. If you followed my explanation just now, you might realize that testing agentNet as a supporting structure to an external agent puts us in the same "agent vs agent with a head start" position we just described. If I wanted to make tests out of this, I'd have to stop looking at effectiveness (the loop would make pass rates converge) and start measuring efficiency (tokens, tool calls, time to solution), which is a whole different battle. Even then there would be a huge wall: coding agents are RL'd to be insanely effective with the tools they already have (grep, glob, semantic search, etc). I built a simple agentNet MCP, but despite my best efforts and system prompts, agents were super resistant to using it, and when they did, it was far from effective. I kept mode one in the introduction as the implementation does work and it is a valid way to use agentNet. Creating the MCP and seeing how strongly agents resisted external tools made for a fun side quest. The idea of creating a small model trained around using agentNet as search, and then pitting it against a generic model (trying to win on cost) also came to mind, but I very quickly decided it'd be way out of scope for what we're doing here.

Knowing that I'd be testing the internal build mode from here on out, the design problem became isolation. Every comparison had to hold the runtime and budget constant and change only the thing under test. That meant splitting the experiment into tracks with capability-matched baselines, and treating the frontier agent simply as a difficulty reference.

On the build track, the question is whether zone owners produce better patches than a generic agent on the same internal runtime:

| Arm | Who acts                    | Runtime                      | What they get                              |
| --- | --------------------------- | ---------------------------- | ------------------------------------------ |
| A0  | cursor-agent (composer-2.5) | Full agentic loop, own tools | Whole repo, no agentNet aid                |
| B0  | Generic agent               | One proposal call, no tools  | Whole repo, naive file ranking, no zones   |
| B1  | Zone owners                 | One proposal call, no tools  | Routing, coordinator packs, zone knowledge |

B1 vs A0 is the comparison to avoid as they are different harnesses altogether. B1 vs B0 is the fair one (same runtime, same budget, and the same Claude model for every agent involved).

## Preliminary results

The first clean internal batch was 6 instances × 2 B arms = 12 cells. Each cell runs the full harness pipeline (pinned worktree, cached index, setup, agent dispatch, validator). The first time all 12 finished without a harness error took days, and the scored run ate most of a day on its own.

![One scored cell, start to finish: pinned worktree, cached index, setup, agent dispatch, validator — with the task set hashed and held-out tests committed before scoring starts](/agentnet/harness-pipeline.png)

### The tasks

These aren't toy prompts by any means. Four are real merged PRs from 2026 and two are held-out analogy tasks with validators written before any scored run.

fastify/fastify

- `pr-fastify-01` ([PR #6746](https://github.com/fastify/fastify/pull/6746)) — chunk large HTTP/2 buffer replies so a cancelled session doesn't get poisoned. Ground truth touches `lib/reply.js` and docs; validated by `test/http2/plain.test.js`. (+187 lines in the reference patch.)

- `pr-fastify-03` ([PR #6881](https://github.com/fastify/fastify/pull/6881)) — catch uncatchable throws from `writeHead` when async `onSend` / `preSerialization` hooks are in play. Fix lives in `lib/hooks.js`.

- `an-fastify-01` — add `Reply.setDecorator(name, value)` following existing decorator patterns. Must update `lib/reply.js` and `types/reply.d.ts` (two sibling leaves). Held-out validator, never happened upstream.

tokio-rs/tokio

- `pr-tokio-02` ([PR #8215](https://github.com/tokio-rs/tokio/pull/8215)) — `StreamMap::poll_next_many` can return more items than its limit when multiple streams are ready in one scan. Fix in `tokio-stream/src/stream_map.rs`.

- `pr-tokio-03` ([PR #8274](https://github.com/tokio-rs/tokio/pull/8274)) — `DelayQueue` misses a wakeup when an item is reset to a past deadline; the poller can sleep while the item is already expired. Fix in `tokio-util/src/time/delay_queue.rs`.

mit-pdos/xv6-riscv

- `an-xv6-03` — add a `getppid()` syscall, wired end to end (`syscall.h`, `syscall.c`, `sysproc.c`, `user.h`, `usys.pl`). Validated in Docker/qemu with a held-out test program. (Even A0 failed this one.)

That last task is the one that later mattered for review (we'll get into this in a second): both B arms tended to patch `kernel/proc.c` and stop.

### Results

| Arm | Pass |
| --- | ---- |
| A0  | 5/6  |
| B0  | 2/6  |
| B1  | 0/6  |

Not a single B1 cell passed. B0 beat B1. This was a scary result to see, agentNet's ownership structure was actively costing correctness.

### Taxonomy saved the project

Nine of the ten failed cells showed the same behavior: the model wrote a plausible test asserting the desired behavior and never touched the source. Despite this looking like a silly bug at first, it resulted in a pretty interesting finding.

Packs were being drawn only from the dispatched leaf, and in all six B1 cells the file that needed editing lived outside it. A model that can't see the file will invent work elsewhere. In real life, changes don't respect ownership boundaries; therefore, a single owner's scope is the wrong unit of context. The coordinator's subtree (the manager who sees across their reports) is closer to right. Obvious in retrospect, but without the tests I would not have realized how critical this was.

Drawing packs from the routed coordinator's subtree (plus one prompt-parity fix on the internal arms) flipped the re-run: B1 went from 0/6 to 3/6 (a strict superset of B0), recovering 60% of the frontier agent's pass rate from a single proposal call with no tools. In pr-tokio-02, using the same model and prompt, the coordinator pack surfaced `src/stream_map.rs` while B0's whole-repo ranking wrote a regression test and skipped the fix. That's agentNet's structure finally showing promise in doing what it was designed for.

## The pivot

Unfortunately, after many more test runs across all the repositories previously listed, the instances of agentNet's structure delivering on its promise were few, far between, and ultimately statistically insignificant. However, closely watching the runs showed one promising pattern which ended up changing the direction of the project.

On the xv6 task (add `getppid()`, which requires touching six files of syscall wiring), both arms produced the same class of incomplete fix: `kernel/proc.c` only. B0 applied it and failed validation. B1's owner for said file rejected it, and named the five missing files the feature would require: `kernel/syscall.h`, `kernel/syscall.c`, `kernel/sysproc.c`, `user/user.h`, `user/usys.pl`. That is exactly, file for file, the set that was created in the human reference patch, which the reviewer had never seen. With the same model and task, the structure was able to provide precisely what was missing, while the unstructured baseline shipped the incomplete change.

So it turned out owners were mediocre at writing changes; what they were startlingly good at was refusing them (with correct, actionable reasons). Again, this seems obvious in hindsight; ultimately, this is how human code ownership works half the time. Your Google code owner doesn't write your CL; they refuse to approve it until it's actually done properly.

So I locked in a new claim: persistent zone owners as ownership-scoped pre-merge review, catching incomplete cross-file work and unlintable local conventions. I wrote a quick claim document including the anti-claims (no longer trying to improve upon SOTA, no trying to win on cost), the evidence bar, and the decision rules for what different outcomes would mean. Then I built the new experiment.

## R0 vs R1

The setup, briefly, since you know the drill by now: 14 review items across xv6, fastify, and tokio: 7 incomplete diffs (real changes with required adjacent files removed, plus partial proposals recovered from earlier runs) and 7 complete controls (reference patches and real merged PRs), all hashed and frozen before the first scored call. Two arms, same model, same budget. R0 is a generalist reviewer given the diff, full post-patch file contents, and a repo orientation, a pretty generous setup, but after so many twists in this project I didn't want agentNet to simply show promise against a strawman reviewer agent.

R1 is the product's real review path: the diff routes to its owning zone and the coordinator reviews it with the owner's scoped knowledge. The endpoints to observe were the following: catch rate on incompletes, false-reject rate on controls, and whether rejections name the actual missing files (more of a diagnostic metric).

It is worth saying that at this point the build experiments had eaten my entire Anthropic API balance, so I found myself at 4 a.m. refactoring agentNet's whole provider layer so the owners could be paid in OpenAI tokens instead (Shoutout @YC 's student pack). The review experiments were therefore run on a mini-tier model.

The results, from the run I was hoping would vindicate the pivot:

| Endpoint (majority over n=3)                 | R0 generalist | R1 zone owner |
| -------------------------------------------- | ------------- | ------------- |
| Incomplete catch (7 items)                   | 7/7           | 6/7           |
| False rejects on complete controls (7 items) | 4/7           | 3/7           |
| Per-run false-reject rate                    | 57%           | 38%           |
| Missing-file recall (caught items)           | 0.35          | 0.01          |

The decision rules I'd locked in advance were pretty blunt: R1 had to beat R0, and despite only trailing by one catch, it didn't. The autopsy complicated that verdict, R0 turned out to be pretty trigger happy, rejecting almost everything, including 4 of 7 real merged changes. But upon re-runs and some reasonable improvements to ensure it wasn't the harness's fault, agentNet still couldn't clear the bar.

I pulled one more thread to see if the problem was model strength, and ran an exploratory batch with a stronger model. This run caught every incomplete and rejected 6 of 7 real merged changes under R1. The effect hit both arms on the same frozen corpus, and the stronger model actually got better at naming missing files (0.01 → 0.39) while its judgment got worse.

So the honest label is inconclusive: the experiment couldn't measure what I built it to measure, because in a one-shot, no-tool review call, no amount of context, be it generalist or ownership-based, lets a model distinguish "complete, mergeable change" from "plausible but truncated change". A reviewer that could go check (list the zone's files, grep for the syscall table, run a probe build) wouldn't have to guess completeness from context. Review needs hands. This would be a fine and concrete finding to base further research on, but chasing it meant a new experiment, new instrumentation, and most importantly, a token runway I no longer had.

## Why agentNet didn't work

The biggest single constraint was the one-shot runtime. Every measured configuration ultimately hit the same wall: a single context-in, proposal-out call, whether building or reviewing, loses to an agent that can iterate and verify. This constraint was built in deliberately, to make the structure measurable, and the measurements are cleaner for it. But it means agentNet was competing against agentic loops with a non-agentic execution model, and by the time this was undeniable, the SOTA had moved: frontier harnesses now do context management inside the loop, with subagents, agentic search, and compaction. The problem I set out to solve organizationally, the top labs were solving procedurally, with far more engineering hours, model access I don't have, and the ability to co-train models against their own harnesses.

In hindsight the original bet was also framed wrong. I made it an effectiveness claim (structure beats a bigger window), but in the regime I could actually test, effectiveness was either saturated or hidden by the loop. The version of the bet that still has legs is about efficiency, and this project never really got to measure it.

The indexer's limited capabilities were also a huge bottleneck that killed the strongest case for my thesis. agentNet's argument is strongest for repos too large for any single context window, and that's precisely where my tree-sitter indexer fell over, overflowing V8's maximum string length (a full-graph `JSON.stringify`) at around 30k graph nodes. Kubernetes, TypeScript, and Go were all out of reach. Django, at 30,453 nodes, was the largest repo that indexed. The product could not reach its own best argument, so every measurement ran in the mid-size regime where a frontier agent's context window is honestly fine.

Using static structure to map behavioral ownership was sketchy. As we saw with the first failures, zones built from directory shape and import graphs confidently routed to the wrong leaf in 6/6 early cells, at stated confidences of 0.82–0.92. Zone knowledge didn't encode things like "changes in this subsystem require a docs update", which is the kind of convention a human owner carries. The org-chart metaphor holds, but we're going to need a better way to build the graph.

With more time and resources I would:

- Give reviewers bounded verification tools and rerun R0/R1, this time with hands and more agentic behavior; I can't help but feel like I didn't give the review thesis the best possible shot.

- Solve context delivery for mode one. As built, the experiment was expensive, and realistically blocked: agents route around an optional tool, so any numbers would have measured MCP adoption rather than pack quality. The interesting work would be in injection, wiring the pack directly into the agent's prompt or harness, where it can't be declined. Once that exists, I'd be able to run further experiments on the efficiency claim.

- Fix the small stuff the experiments priced out: reviewers should get a list of the zone's files, and a rejected proposal's retry should be allowed to open the files the reviewer names. As built, the xv6 retry tried to edit exactly the file the reviewer pointed at, and the product refused because that file wasn't in the original pack. agentNet knew what was wrong and wasn't allowed to fix it.

- Rebuild the indexer for streaming persistence so the giant-repo regime is testable at all.

- Derive zones from git history and code review data instead of static structure alone, using actual touch and review history as another ownership signal.

- Run everything at an n where I'm not reading so hard into six-task flips.

## Appendix: what went right

Here are some of the good things I am taking away from the experiment (a more personal section).

If you want to take a stab at agentic code owners, here are the most concrete things I can tell you for free. One: an owner scoped only to its own files will starve the agent doing the work; real changes don't respect ownership boundaries, so plan for the coordinator's subtree being the smallest useful unit of context. Two: completeness is not visible in context. A mergeable change and a plausible-but-truncated one look identical from inside a one-shot review call, and no amount of context fixes that. Completeness is a property of the repository, not the diff: the only way to know whether the syscall table got updated is to go look at the syscall table. Review needs hands, ownership should really only decide where the hands go first. Three: if your product's value is context, don't deliver it through a tool the agent has to _choose_ to call. Agents are RL'd to trust grep and their own file reads; they will route around your MCP no matter what the system prompt says. Inject the context up front or don't bother.

I've been around research through university and a general interest in the sciences, but this was the first time I fully applied those principles to my work with agents, and I'm pretty proud of how it went: claims registered before the runs that tested them, decision rules locked in advance, frozen task sets, and a harness that tagged every result with exactly what produced it. That discipline is the only reason I can tell you precisely why the thesis failed and learn from it. It caught the B0-beats-B1 result that killed the naive design in week one, and it forced me to write "does not meet the bar" where a Twitter thread of cherry-picked demos would have said "promising early results!" Your benchmark exists to catch you.

Kontext works, and despite being born to serve agentNet, it has outlived it. With Kontext, agents can run as ordinary Kubernetes workloads, persistent agents get restarted automatically when they die, and every execution is a bounded, auditable run. Because Kontext never learned what a "code owner" is, it shares none of agentNet's fate.

Overall, despite the verdict hovering between "fail" and "inconclusive", I am happy with how it went. Carrying this random idea through got me to build a twelve-language indexer, a Kubernetes operator, and a really solid benchmark harness, among many other cool things. I'm also happy to be putting this idea out there for anyone to experiment with in the future!

Personal note: I am a rising senior studying computer science at UT Austin, and this was one of the projects I spent my junior-year summer on. If you're looking to hire people who get working with agents, who know how to benchmark, and who will tell you when the numbers say no, I'm looking for full time roles starting in May.
