The Graph That Learns: Building Self-Improving Agent Loops A developer has built a prototype of a self-improving AI agent that combines agent loops with graph-based memory to accumulate knowledge from completed tasks. The system records task outcomes, file relationships, and reviewer information in a graph, enabling the agent to start future similar tasks with prior context instead of from scratch. This approach aims to give agents institutional memory, making them more efficient at solving recurring problems. AI agents are getting very good at doing things. They can read a ticket, modify code, open a pull request, query an API, send an email, and keep going until a goal is reached. But there is a problem hiding underneath all of this: Most agents don't actually get smarter from doing the work. They execute a loop, finish the task, and forget what happened. The next time the same problem appears, they start over. That feels wrong. A useful agent shouldn't just complete tasks. It should accumulate knowledge about how to complete those tasks better. This is where two ideas become extremely powerful when combined: Agent loops provide action. Graphs provide memory. And when the graph is updated by the agent's own experience, you get something much more interesting: A self-improving system. In this post, we're going to build a small version of that idea. Consider an engineering agent with this goal: Fix the failing checkout test. The agent might: Read issue ↓ Inspect repository ↓ Find failing test ↓ Inspect implementation ↓ Modify code ↓ Run tests ↓ Fix failure ↓ Open pull request Great. But tomorrow another checkout test fails. The agent starts from scratch. It doesn't remember: The agent has intelligence. But it has no institutional memory . That's a huge difference. At its simplest, an agent is not magic. It's a loop: Goal ↓ Observe ↓ Choose action ↓ Execute ↓ Check result ↓ Repeat We can write that conceptually as: js while goalComplete { const observation = observe ; const action = decide observation, ; const result = execute action, ; check result ; } This is the core of an agent. The model provides reasoning. Tools provide capabilities. The loop provides persistence toward a goal. But there's another component we need. Learning. Imagine the agent completes a task. Instead of simply returning: Task complete. it records what happened: Task: Fix checkout timeout. Observation: Checkout requests were being retried twice. Action: Changed retry behavior in checkout.ts. Result: Tests passed. Related files: payments.ts retry.ts Reviewer: maya Outcome: Merged. Now imagine that the next checkout problem occurs. The agent can see this previous experience. Instead of starting from zero: What is checkout.ts? it can start with: Previous changes to checkout.ts indicate that retry.ts and payments.ts are frequently involved. A previous fix modified retry behavior. Let's inspect those relationships first. That's a dramatically better agent. But there is an important question: How should we store the memory? You could dump everything into a document. Something like: Previous task: Checkout timeout. Files: checkout.ts payments.ts retry.ts People: Maya Bobby Solution: Changed retry behavior. This works. Until you have 10,000 tasks. Then you have a giant pile of text. The interesting information isn't just the facts. It's the relationships . For example: Task │ ├── affected → checkout.ts │ │ │ └── related → retry.ts │ ├── fixed-by → commit 823 │ ├── reviewed-by → Maya │ └── resulted-in → merged PR Now we have a graph. And graphs give us something extremely useful: Traversal. We can ask: What happened to this file? Who worked on it? Who reviewed those changes? What other files changed with it? Which previous tasks touched this area? Which approaches worked? Which approaches failed? The agent doesn't need to remember everything. It needs to know where to look . Let's build a small prototype. Our agent will have one goal: Investigate a failing test. It will have four tools: type Tool = | "search code" | "read file" | "run tests" | "inspect history"; And it will maintain a graph containing: Task File Test Change Person Outcome Relationships will include: AFFECTS READ MODIFIED FIXED FAILED REVIEWED RELATED TO The important part is that agent activity becomes graph data . Create a simple graph implementation: type NodeType = | "task" | "file" | "test" | "change" | "person" | "outcome"; type Relationship = | "AFFECTS" | "READ" | "MODIFIED" | "FIXED" | "FAILED" | "REVIEWED" | "RELATED TO"; type Node = { id: string; type: NodeType; label: string; metadata?: Record