9 September 2026
15 min read

An agent is only as good as its context

By Tim Rutte, Cloud & Software Architect

Second Brain for AI agents, article image

At the end of August I started writing my knowledge into a Git repository. Not because I could not find my notes. Because I was tired of telling the same backstory at every new problem: which systems I run, what my projects are called, what I decided three weeks ago and why.

The common answer to that problem is a better prompt or a larger context window. Both miss the bottleneck. The bottleneck is not how much a model can read at once. The bottleneck is what exists at all in a form it can read from, before you ask the question.

Nine days later the system consists of 334 Markdown files. Nine automations write into it without me starting them, and a Grafana dashboard tells me when one of them stops. What follows is what held up, what did not, and which part of it applies to a team rather than to one person.

The problem was not forgetting, it was repeating

My knowledge sat where most people's sits: in mail, in chat histories, in a document archive, in individual project repositories, and to an uncomfortable extent in my head. That was fine for a long time, because I was the only reader and I know where I look.

It became a problem when an agent started doing real work. Every session began at zero. I explained that there are two brands and what each stands for. I explained which server runs what. I explained a decision I had made, because otherwise the option I had already rejected got proposed again.

The expensive part was not the typing. The expensive part was that every answer rested on a summary I had assembled from memory in that moment. It came out slightly different each time and slightly incomplete each time. The agent was not bad. It was working on a source that did not exist.

So the decisive shift was not about filing. It was the question of what a model has to be able to read before it answers. Everything else follows from that.

Why Markdown and Git and nothing cleverer

The founding decision is dated 31 August and sits as a decision record inside the repository itself: plain Markdown files in a Git repository are the single valid source. I rejected three obvious alternatives, and the reasons matter more than the choice.

An Obsidian vault as the basis. Rejected because of tool lock-in. Once database features and plugins carry the structure, only that one program can read the structure. As a viewer and editor Obsidian stays useful, the repository works with it, but it does not depend on it.

The memory built into the models. Every vendor now has its own recall feature. Rejected because it is fragmented, opaque and not portable. I cannot see what was stored, I cannot version it, and I cannot get it out. As ephemeral scratch memory that is fine, as a source of truth it is not.

A database. Rejected because at this scale it gains nothing and loses two things: readability for humans and a usable history. A row in a table does not say why it changed. A Git diff does.

What Markdown and Git deliver instead is unspectacular and load-bearing for exactly that reason. Any agent that can read files can operate the system. Git provides history, sync across devices, an audit trail, and the safety net that makes autonomous restructuring defensible at all.

The operating manual is itself a file. AGENTS.md describes in a model-neutral way how to read, write and decide; the file for Claude Code merely imports it. Fifteen skills are thin wrappers over sixteen workflows that are written model-neutrally as well. A different model follows the same documents directly. That is not purism, it is a bet that in two years I will be using a different tool than today.

Built for a reader that is a machine

At the top sit ten numbered directories, ordered roughly by where an agent should look first: the control plane with architecture, principles, indexes and templates, an inbox, the journal, projects, ongoing responsibilities, people, knowledge, decisions, external material, and the archive.

More important than the tree is the reading order, and it sits as a rule in the operating manual: never load everything. First the file holding the current focus, then the indexes, then the one canonical file, then whatever is linked from it, and the journal only when the question is about the past. Anyone who has built a retrieval strategy knows the movement; here it is expressed in directories rather than in an index.

One single observation then changed the design more than any structural consideration: I do not read these files. I ask a model that searches them. When the agent asked me which of three task lists I actually open, the honest answer was: none of them.

Three things follow from that, and they contradict most of the advice out there.

Duplication is the most expensive mistake. Two copies of a statement drift apart, and neither carries a marker saying which one is current. A model then answers the same question differently depending on which file it loaded, and convincingly both times. One long canonical file beats two short ones.

Length is allowed, redundancy is not. A size warning is a reason to look, not an instruction to cut. What stands complete once behind a link is allowed to be thorough.

Findability beats beauty. Descriptive headings and unambiguous anchors pay off. A pretty, shallow directory tree does not pay off if nobody looks at it.

The inbox nobody uses

Every guide to personal knowledge systems starts the same way: capture everything first, sort it later. The inbox is the central idea, and I dutifully created one, with a separate file per note so that several devices can write into it at once without Git running into conflicts.

Then the agent counted. Across the entire history of the repository exactly one note has gone through the inbox, while more than two hundred documents were written straight to the place responsible for them. Today it is empty.

The reason is simple: when I contribute something in a session, the right home is usually obvious, and putting it into a holding area first is ceremony without benefit. The inbox stays anyway, but for the case it was meant for: a note away from the desk, with no session and no filing decision.

That is a small thing with a general lesson. A workflow that sounds convincing in a book can be measured against your own history instead of believed for years. It costs one counting command.

Knowledge stays, structure may change

The system's guiding principle fits in one sentence: preserve knowledge, evolve structure. Information is permanent, organization is version one and is allowed to improve.

In practice that means an agent may move, rename, merge and split files without asking, as long as it updates every reference and logs the change. What it may not do without explicit consent is stated just as plainly: delete historical information, irreversibly remove raw notes, send confidential content outside, store secrets, run mass cleanups. When in doubt it archives rather than deletes.

In nine days that has produced 64 logged structural changes, each with an observation, the change, a reason, a result field, and a note on whether it is reversible. That sounds like a lot, and it is. It is only defensible because Git sits underneath: every one of those changes is a diff I can read, and every one can be taken back.

Autonomy without version control would be reckless. With version control it is the reason the system is better sorted today than on the day I designed it.

A rule no mechanism checks does not hold

This is the lesson that made the whole exercise worthwhile, and I learned it from a triviality.

I do not want to see long dashes in text. The reason is not typography, it is that to me they look like machine-generated writing. The rule sat in four places: in the operating manual, in the file for Claude Code, in the pattern catalogue, and on top of that in the model's own memory.

It was broken twice by sessions that knew it. Once in chat answers, once in twenty added lines of a nightly cleanup run. Both times what found it was not reading, it was a search command over the diff.

The same pattern in two other places in the same period. Invented values in the metadata: four were rolled back and the rule written down, and in the two days after that three new ones appeared. Only once a mechanical check was added did the next one get reported instead of committed. And a heartbeat for the cloud runs that was described in two workflow documents and implemented in neither prompt: the monitoring against silent failure was itself one.

The conclusion is uncomfortable, because it rules out the comfortable reflex. When a convention gets broken, the wrong lever is to word it more forcefully. Someone who does not read a rule will not read the bold one either. The question is instead: can the same sentence be written as a check? If it can, the check is the rule, and the text beside it is only the reasoning.

Three such checks run today before anything is committed: one over links, anchors and metadata types, a search command over the diff for the dashes, and one that finds accidental deletions. The limit of the method belongs with it: it applies to conventions about form, metadata and filing, the kind that can be decided mechanically. What counts as a fact and what gets recorded in full is still decided by a person.

If that sounds familiar: it is exactly the core of what I build when introducing Claude Code into a team. An architecture rule an agent is supposed to read is not a rule. An architecture rule a pipeline enforces is one.

A check that reports green in silence

The follow-up to that lesson arrived four days later and cost more.

The script that checks internal links and anchors took a line of prose for the start of a code block, because it began with three backticks. The block was never closed, so the script skipped the rest of the file. Roughly 520 of 1,015 lines went unchecked for four days. During that time every run reported, reliably: zero findings.

It only came to light because a rebuild in exactly that area produced real errors and the check did not see them.

The damage is not the gap. The damage is the trust the green message creates and does not cover. Someone without a check looks for themselves. Someone with a green message stops looking.

The answer to that is a canary: a file with a deliberately broken link that every full run has to find. If it does not find it, the run exits with an error instead of reporting success. Next to it sits a second check for precisely the failure mode that occurred, namely any file that ends inside a code block. The canary alone would not have caught that case, because the machinery was running.

The question that has since stood at the start of building any monitoring is: what does its failure look like? If the answer is "like success", the monitoring is not finished. In practice that means no silent skipping, no continuing without counting, no empty result that cannot be told apart from "nothing found".

My page about introducing observability carries the related sentence: outages are reported by customers, not by the system. I wrote that for client systems. That it applies just as much to the checks I run over my own notes only occurred to me here.

What the system does today without me

Nine automations write into the repository or read from it without me giving a command.

Four bring material in. A run at 06:30 distils new documents from the document archive into the files responsible for them, one commit per document. At 07:15 a second does the same with relevant mail threads and pulls out facts, commitments, deadlines and people. At 05:00 a third condenses the previous day's messages into the daily note. At 04:30 a fourth reads every calendar and rewrites the appointment overview, today plus 180 days ahead.

Two keep the system in shape. A cloud run creates missing journal notes in the morning, a second empties the inbox into the canonical folders in the evening. An empty run writes nothing but its heartbeat, which matters more than it sounds: something that runs every night usually finds nothing, and an automation that produces something anyway generates noise instead of quiet.

Three work at the surface. An exporter reads the repository every 15 minutes and never writes to it. A morning briefing posts appointments, deadlines and whatever has been left lying into a private channel at 06:30, plus an hourly escalation check that only reports on a hard trigger. And an agent reads that same channel, answers out of the repository, and changes it when I explicitly ask, with one action per commit so each one can be taken back on its own.

On top of all that sits the same monitoring I build for clients: metrics as files, Prometheus, a dashboard, nine alert rules. Two of them do not watch the automations but the repository itself: one for every internal link whose target does not exist, and one for the case that the check behind it has stopped checking.

What that changes for me is more mundane than the list suggests. I get reminded in the morning of things I would otherwise put off. What has been left lying becomes visible instead of quietly getting older. And a share of my tasks now comes into being without me writing them down, because they fall out of a mail or an appointment.

One part of it is not clean, and I would rather say so myself: the briefing carries confidential content out into a chat channel. That is a deliberate trade, protected only by the channel being private. The safeguard is the channel, not the content.

What does not work

The system has a learning loop: observe, detect a pattern, form a hypothesis, make a small reversible change, use it, evaluate, keep or revert. It is documented properly, and it turns reliably up to "change made".

Then it stops. Of the 64 logged changes, 59 still say "open" in the result field. Four have been evaluated. Which means the system documents its rebuilds exemplarily and assesses them almost never. That a reverted change counts as a success is written in the description. It only works if somebody looks, and so far that is the step that fails.

Second, the dashes from two sections ago. New text is clean because a check stands in the way. In the existing files, 248 still contain the character. Not corrected, because that would be a diff across half the repository, and the task sits in a backlog, which is a polite way of saying: not done.

Third, and this qualifies everything above: nine days is not evidence. Every number in this article comes from a system that is nine days old. Whether the order still holds after a year, whether the automations are still running then, and whether I ever close the evaluation loop, I do not know. Anyone selling you a method after nine days is selling you a guess.

What carries over to a team

This is a personal system, and the directory tree in it is the least interesting part. What carries over is three sentences, and they apply to a team more harshly than to one person.

One fact, one place. As soon as the same statement is maintained in two places, an agent answers the same question differently depending on what it loaded. In a team with a wiki, a ticket system and three repositories that is the normal state, not the exception.

A rule without a mechanism does not hold. That applies to architecture rules in a codebase exactly as it does to dashes in notes. If you let agents into your code, you need the enforcing layer first, not afterwards.

A check that reports green in silence is worse than none. That is not a new insight from running distributed systems. What is new is how quickly you relearn it in a knowledge system.

The reason this occupies me professionally sits in my own Legacy Risk Score: knowledge and dependencies are one of four dimensions there, and the one where the answer is never a tool. A team where three people know how deployment works does not have a documentation problem. It has a problem with its knowledge sitting nowhere in a form somebody else can read, human or machine.

What that looks like concretely when agents are meant to work inside a codebase is in my article on agentic coding with spec-driven development. This article is the layer beneath it: the knowledge a specification can come from in the first place.