<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonathan Berg</title>
    <description>The latest articles on DEV Community by Jonathan Berg (@jonathanmberg).</description>
    <link>https://dev.to/jonathanmberg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4106872%2Fb718acb7-7bc5-443a-9397-2e883bc2524d.jpg</url>
      <title>DEV Community: Jonathan Berg</title>
      <link>https://dev.to/jonathanmberg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonathanmberg"/>
    <language>en</language>
    <item>
      <title>Save the method, not just the result</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 27 Oct 2026 14:26:57 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/save-the-method-not-just-the-result-52ce</link>
      <guid>https://dev.to/jonathanmberg/save-the-method-not-just-the-result-52ce</guid>
      <description>&lt;p&gt;I have spent most of this year thinking about what coding agents should remember. Almost all of the attention goes to things. The component you finally got right. The fix you never want to derive again. Those are worth keeping, and I have written about them here before. But a good run produces something else that is usually thrown away: the method that got to the result.&lt;/p&gt;

&lt;p&gt;Watch a strong model do a task well once. Sorting a messy batch of documents against a company's own rules. Reviewing a diff the way a careful senior engineer would. The answer matters for a day. The way the model got to the answer is what you will need again next week, and in most setups it evaporates. The next time the task shows up, you rerun the expensive model and hope it reasons the same way twice.&lt;/p&gt;

&lt;p&gt;That is a strange way to treat the most valuable part of the run.&lt;/p&gt;

&lt;h2&gt;
  
  
  A result ages, a method keeps working
&lt;/h2&gt;

&lt;p&gt;Say an agent works out a careful procedure for checking supplier invoices against your rules. Which fields to read first. Which mismatches matter and which are noise. When to stop and hand the decision to a person. If all you keep is the classified batch, the next batch starts from zero. If you keep the procedure, the next batch starts from a flow that already proved itself.&lt;/p&gt;

&lt;p&gt;This is the same shift I wrote about when I argued your agent should start from your library. Components moved the starting line from nothing to something. Methods move it further. A component is what you built. A method is how you work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Written methods let weaker models do stronger work
&lt;/h2&gt;

&lt;p&gt;There is a second effect, and it might be the bigger one. Once the procedure exists as text, you no longer need the strongest model for every repeat. The hard thinking happened once. A cheaper model can follow the flow.&lt;/p&gt;

&lt;p&gt;You do not have to take that on faith. Run the cheaper model against cases where you already know the right answer and keep the runs where it passes. The question stops being which model is best in general and becomes which model has proven it can follow this method on your work. That is a question you can answer with evidence instead of vibes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every run is evidence
&lt;/h2&gt;

&lt;p&gt;When a saved method gets reused, each run teaches you something. Which model ran it. Whether it passed. Whether a person confirmed the result or it was checked against known answers. Over time the library stops being a pile of text and becomes a record of what actually works, with the receipts attached.&lt;/p&gt;

&lt;p&gt;Versions matter here too. A method will get edited as the work changes, and you want to see when an edit helped and when it quietly broke a run that used to pass. Memory without history is just the latest opinion.&lt;/p&gt;

&lt;p&gt;This is the idea behind Playbooks, which I added to Sirro last week. Do the task once with the best model you have, save the method, and let the library show you the cheapest model that still passes on your own examples.&lt;/p&gt;

&lt;p&gt;Components made my agents start from what I built. Methods make them start from how I work. The best run your agent had this month should still be working for you next year.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>mcp</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A reusable component needs a boundary, not a fixed size</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 20 Oct 2026 13:26:47 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/a-reusable-component-needs-a-boundary-not-a-fixed-size-1c0</link>
      <guid>https://dev.to/jonathanmberg/a-reusable-component-needs-a-boundary-not-a-fixed-size-1c0</guid>
      <description>&lt;p&gt;I don't think a reusable component has a useful fixed size. A button can be worth keeping. So can an entire sign-in flow. The question I care about is whether an agent can take the work into another project without making me explain the missing half.&lt;/p&gt;

&lt;p&gt;This matters when you start saving work from coding-agent conversations. In the conversation, everything has context. The agent knows which files it just changed, which package you installed and why you rejected the previous version. Pull the final code out of that conversation and some of those assumptions disappear. You can save the right code and still lose what made it work.&lt;/p&gt;

&lt;p&gt;That is a different problem from finding the code again. Retrieval can be perfect and the saved work can still be awkward to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The useful boundary follows the work
&lt;/h2&gt;

&lt;p&gt;Suppose I save a button that depends on a theme provider. The component looks self-contained until I move it to a project without that provider. Now the agent has to discover the dependency, work out whether to bring it across and decide how to connect it to the new project's styles.&lt;/p&gt;

&lt;p&gt;Saving the entire application would avoid some missing context, but it would create another problem. I wanted a button, not the routing, data model and deployment choices of the project it came from.&lt;/p&gt;

&lt;p&gt;The boundary I want sits between those extremes. Keep the work I chose, along with enough information to understand what it expects around it. A dependency does not always need to be copied into the asset. Sometimes naming it and explaining why it is there is enough. What matters is that the next agent does not have to discover it by breaking things.&lt;/p&gt;

&lt;p&gt;An auth flow has a larger boundary because the useful behaviour crosses files. Breaking it into isolated snippets can make it less reusable. The callback handling and the session checks belong to the same piece of work even if they are nowhere near each other in the repo.&lt;/p&gt;

&lt;p&gt;I would rather save a complete idea than force everything into the same shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leave room for the next project
&lt;/h2&gt;

&lt;p&gt;There is also a difference between the part I want to preserve and the part I expect to change. The behaviour might be worth keeping exactly while the styling needs to fit a new site. An integration pattern might be reusable while its environment configuration belongs entirely to the next project.&lt;/p&gt;

&lt;p&gt;If I don't make that distinction clear, the next agent has to choose for me. It might preserve something that should change, or rewrite the thing I saved it to avoid rewriting.&lt;/p&gt;

&lt;p&gt;This is where I think AI is useful as glue. It can connect a known piece of work to a new setting. I still want it to reason about the differences. I just don't want every difference to become an excuse to generate the whole thing again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reuse is the check
&lt;/h2&gt;

&lt;p&gt;A component that worked in its original project has passed a useful test, but it has not yet shown me that I chose a good reusable boundary. Moving it somewhere else exposes the assumptions I forgot to save.&lt;/p&gt;

&lt;p&gt;That is how I want to think about the library I am building with Sirro. Saving is a starting point. Each reuse should help me understand whether the saved work includes too much, too little or the right amount of context.&lt;/p&gt;

&lt;p&gt;The goal is not a library full of equally sized pieces. It is a library where the next agent can tell what a piece does, what it needs and what can change. Then the work I finished in one conversation can actually become a building block in the next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>DIY agent memory works until you have to maintain it</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 13 Oct 2026 13:28:20 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/diy-agent-memory-works-until-you-have-to-maintain-it-3c89</link>
      <guid>https://dev.to/jonathanmberg/diy-agent-memory-works-until-you-have-to-maintain-it-3c89</guid>
      <description>&lt;p&gt;A question I keep hearing about Sirro is some version of this: why should a team use a service when they could set up their own git repo, put every reusable asset in a named folder with its context, and write a skill that tells the agent how to store and retrieve things?&lt;/p&gt;

&lt;p&gt;I think it is the right question to ask, and I want to answer it honestly. For some teams, that setup is enough. If you are one developer, working in one agent, on one project, a repo and a skill file will take you surprisingly far. I would never tell that person to buy a service.&lt;/p&gt;

&lt;p&gt;The interesting part of the question is not whether the DIY version works. It is what you are responsible for once it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day one is easy, month three is the product
&lt;/h2&gt;

&lt;p&gt;With a git repo plus a skill, your team has to define the structure itself. Someone decides how assets are named, what context lives next to each one, and how an agent is supposed to find the right thing. Then someone has to write and maintain the logic for how things get stored and retrieved, and make sure every agent and every project has the correct setup. Not once. Every single time.&lt;/p&gt;

&lt;p&gt;That last part is where I have seen this fall apart, in my own work before Sirro existed. The repo does not break loudly. One project gets an older version of the instructions. A folder gets renamed and the skill file still points at the old one. A second agent gets connected and nobody updates its setup, so it retrieves nothing and regenerates instead. Each individual failure is small, so nobody fixes the system, and after a while people stop trusting the library. An asset library nobody trusts is just a folder of old code. The first time someone asks "is this still current?", you have lost most of the value.&lt;/p&gt;

&lt;p&gt;The real cost is that the team becomes the maintainer of a small internal product, forever, on top of the product they are actually paid to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a service takes over
&lt;/h2&gt;

&lt;p&gt;When we built Sirro as a shared library instead of a template, the point was to move that maintenance burden into one place. The structure, the storage and the retrieval logic are maintained once, by us, and every connected agent and project reads from the same library without a per-project setup step. When an asset is updated, there is one shared source, not copies drifting apart across repos.&lt;/p&gt;

&lt;p&gt;There is also a plain economics argument. Regenerating work you have already done costs tokens every time. In our internal tests, reusing saved work instead of regenerating it cut token use by 70 to 95 percent, depending on the task. That saving only exists if retrieval actually works. When a DIY setup quietly fails, the agent does what agents do: it builds the thing again from scratch, and you pay for the work twice while believing you paid once.&lt;/p&gt;

&lt;p&gt;I want to be clear that the repo approach is not wrong. It is a real answer, and for a solo developer it might be the best one. The mistake is choosing it based on how it looks on day one, when the team, the agents and the projects you will have in three months are what the decision is really about. My answer is simple: anyone can build software faster now. The question is who maintains the system for keeping what you built. I would rather maintain it once, properly, for everyone.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Onboard your coding agent once</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 06 Oct 2026 13:27:03 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/onboard-your-coding-agent-once-15c3</link>
      <guid>https://dev.to/jonathanmberg/onboard-your-coding-agent-once-15c3</guid>
      <description>&lt;p&gt;I think onboarding a coding agent should be work you do once. If I have already explained how a project works, I want the next agent to pick up that explanation instead of making me write it again. Connecting a tool gives the agent access to it, but I still need a way to tell it how we use that tool in this project.&lt;/p&gt;

&lt;p&gt;This weekend I added an onboarding Pack to a shared Sirro library. The starting point was simple: open a new chat, ask Claude to use the Sirro onboarding Pack, then ask it questions about Sirro. Instead of explaining the product through another long message, I could give the agent a named piece of work to read.&lt;/p&gt;

&lt;p&gt;That made me think about what I actually want to keep between sessions. The code is part of it. The explanation of how to work with that code is worth keeping too, especially when someone else joins the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The explanation belongs with the work
&lt;/h2&gt;

&lt;p&gt;When I build software for clients, there are decisions I end up explaining repeatedly. A piece of code can be perfectly readable without telling the next person why I chose it or what I expect them to leave alone. An agent can inspect the repo and still miss the reason behind a decision.&lt;/p&gt;

&lt;p&gt;I want to save that explanation while it is still clear. If a conversation finally gets the agent working the way I need, the useful instructions should be easy to pull into the next conversation. Having to search an old chat and reconstruct them defeats much of the reason for saving the work in the first place.&lt;/p&gt;

&lt;p&gt;For Sirro, I started with its own onboarding. The request I gave someone to try was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use the Sirro onboarding Pack from our team. How does Sirro work?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like that the developer can start with a question. They should be able to ask how to use the library through the agent they are already working with. They shouldn't have to become an expert in my dashboard before they can retrieve something useful.&lt;/p&gt;

&lt;p&gt;The same idea could apply to onboarding a consultant to a project. You have already done the work of explaining how the team builds. Give that explanation a name and keep it somewhere the next person and their agent can use. You can improve it as the project changes, rather than maintaining a slightly different introduction in every chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the useful introduction small
&lt;/h2&gt;

&lt;p&gt;I wouldn't put the whole project history into an onboarding Pack. I want enough to start working correctly and know where to look next. Loading months of conversation into a new session would bring back much of the noise I was trying to leave behind.&lt;/p&gt;

&lt;p&gt;A useful introduction should answer the questions people actually ask when they join. If I have to correct the same misunderstanding every time, that correction belongs in the introduction. If an explanation only mattered during one debugging session, I would leave it with that work until there is a reason to reuse it.&lt;/p&gt;

&lt;p&gt;There is a maintenance cost here. Saving an introduction doesn't keep it true forever. When the project changes, someone has to update it. I would rather maintain one shared explanation deliberately than let old instructions survive unnoticed in several different tools.&lt;/p&gt;

&lt;p&gt;I also wouldn't assume that retrieving a Pack means the agent understood it. I would ask it a concrete question about the project and inspect the answer before handing it a bigger task. A named document gives us something to check against when it gets the answer wrong.&lt;/p&gt;

&lt;p&gt;This is the part of agent memory I want to get right: the time I spend explaining my work should improve the next session. I should be able to bring in another developer, start a new chat, and build on the explanation we already worked out. The onboarding itself becomes reusable work.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>mcp</category>
    </item>
    <item>
      <title>The real test for agent memory is switching agents</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 29 Sep 2026 13:26:40 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/the-real-test-for-agent-memory-is-switching-agents-1ll5</link>
      <guid>https://dev.to/jonathanmberg/the-real-test-for-agent-memory-is-switching-agents-1ll5</guid>
      <description>&lt;p&gt;I built Sirro because I kept running into the same problem while building apps for clients. I would get a section working in one project, start another, and then explain it to a coding agent all over again. The second version was close, but it was never quite the thing I had already made.&lt;/p&gt;

&lt;p&gt;The problem gets more obvious when you switch tools. You save your work in one agent's project files, then open a different agent and find yourself back at the beginning. The first tool may remember the conversation perfectly. That doesn't help much if the next tool can't use the finished work.&lt;/p&gt;

&lt;p&gt;I've been thinking about how to test whether a shared library actually fixes this. It is easy to make a demo where an agent retrieves a snippet from the same tool that saved it. The harder test is to change the agent, change the project, and see whether you still get the thing you meant to keep.&lt;/p&gt;

&lt;h2&gt;
  
  
  A test I would trust
&lt;/h2&gt;

&lt;p&gt;Start with a working piece of code in a real project. Something specific enough that rebuilding it from a prompt would lose details. Save it through one coding agent, then close that project. Open a fresh project in a different tool and ask for the same piece by name.&lt;/p&gt;

&lt;p&gt;At that point, I want to know what actually came back. Did the new agent retrieve the saved code, or did it generate something that merely looks similar? Can I see which version it used? Will it work in the new project without quietly dropping the behavior that made the original worth saving?&lt;/p&gt;

&lt;p&gt;I also want to try a third tool that wasn't part of the original save. If the library only works when I stay in the tool where I made the asset, then it is another local memory with a nicer interface. Portability has to survive the handoff.&lt;/p&gt;

&lt;p&gt;This is a test plan, not a claim that every coding agent already passes it. Sirro's beta has had real authentication problems, and getting someone into the product is part of the test. A perfect retrieval flow behind a sign-in that fails for a new user isn't useful. We spent part of this week fixing that before asking anyone to judge the library itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Save the result, then test the transfer
&lt;/h2&gt;

&lt;p&gt;A lot of agent-memory discussion starts with what an agent can remember about you. That matters, but for coding work I keep coming back to the artifact. The reason I save a section is that I want that section again, including the small decisions I don't want to explain twice.&lt;/p&gt;

&lt;p&gt;A good memory system should make it possible to tell the difference between retrieval and imitation. If an agent says it used something from my library, I should be able to inspect the original asset and the version it pulled. Otherwise a plausible output can hide the fact that the work was rebuilt from scratch.&lt;/p&gt;

&lt;p&gt;I don't think a standard format or a shared folder settles this on its own. Those can make an asset available. The useful question is whether I can move between the tools I actually use, name the work I already did, and keep its important details intact.&lt;/p&gt;

&lt;p&gt;That is the test I'm interested in now: make it once, switch agents, and see if the next one can really pick it up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>mcp</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Agent memory needs an editor</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 22 Sep 2026 13:29:06 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/agent-memory-needs-an-editor-3c3</link>
      <guid>https://dev.to/jonathanmberg/agent-memory-needs-an-editor-3c3</guid>
      <description>&lt;p&gt;I have been thinking about what happens when several agents share the same memory.&lt;/p&gt;

&lt;p&gt;The obvious version is a database they can all read and write. A coding agent saves a useful pattern. A browser agent adds research. A personal agent records a decision. The next agent opens the workspace and starts with everything the others learned.&lt;/p&gt;

&lt;p&gt;That sounds powerful until two agents disagree.&lt;/p&gt;

&lt;p&gt;One agent marks a component as the preferred version. Another replaces it after a failed run. A third saves a summary without seeing the original decision. If every write has equal authority, the shared memory slowly becomes a pile of confident contradictions.&lt;/p&gt;

&lt;p&gt;The difficult part of multi-agent memory is not storage. It is deciding what gets to become true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared memory creates a merge problem
&lt;/h2&gt;

&lt;p&gt;Developers already know this problem from Git. Many people can work on the same codebase because changes have authors, diffs and a path to merge. We do not let every branch silently rewrite main.&lt;/p&gt;

&lt;p&gt;Agent memory needs the same basic discipline.&lt;/p&gt;

&lt;p&gt;A useful memory entry should keep its source, the agent that proposed it, the work that produced it and the decision that accepted it. When something changes, the system should preserve the old version long enough to explain what happened.&lt;/p&gt;

&lt;p&gt;Without that history, an agent cannot tell the difference between a tested decision and a guess saved five minutes ago.&lt;/p&gt;

&lt;p&gt;This matters more as agents move beyond code. A coding agent may know that an integration failed for a specific technical reason. A browser agent may later see updated documentation and conclude that the old limitation is gone. Both observations can be valid at the time they were made. Replacing one sentence with the other throws away the part that makes the knowledge useful.&lt;/p&gt;

&lt;p&gt;The memory needs to carry the change, not only the latest text.&lt;/p&gt;

&lt;h2&gt;
  
  
  One agent should hold merge authority
&lt;/h2&gt;

&lt;p&gt;My current view is that a shared workspace needs a primary agent. That agent does not need to do every task. It needs to decide what becomes part of the durable memory.&lt;/p&gt;

&lt;p&gt;Other agents can propose additions and corrections. They can attach evidence, point out stale knowledge and suggest that an asset should be replaced. The primary agent can accept, reject or ask for more context.&lt;/p&gt;

&lt;p&gt;This gives the workspace a clear authority model. A temporary agent used for one task cannot silently rewrite a decision that every other agent will trust tomorrow.&lt;/p&gt;

&lt;p&gt;The human still sits above the system. They can pin a decision, change which agent has authority or inspect why something was accepted. The point is to make those boundaries visible instead of pretending all agent output deserves the same weight.&lt;/p&gt;

&lt;p&gt;Silent self-editing is especially dangerous here. If an agent can change its own instructions or the shared memory after a failed run, it may improve. It may also erase the evidence of why it failed. Proposed changes should be reviewable events, even when another agent handles the review automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory should become more trusted as it is used
&lt;/h2&gt;

&lt;p&gt;A good shared memory should learn from reuse.&lt;/p&gt;

&lt;p&gt;If an asset is saved, retrieved and used successfully across several projects, that is evidence. If agents keep pulling it and then rewriting it, that is evidence too. Usage can tell the primary agent which parts of the library are stable and which need attention.&lt;/p&gt;

&lt;p&gt;This is more useful than treating every saved item as permanent. Some knowledge should expire. Some should be tied to a version, environment or client. Some should remain a proposal until it has survived real work.&lt;/p&gt;

&lt;p&gt;The library becomes valuable because it records decisions and their outcomes. More agents writing to it should increase that value, as long as they cannot quietly overwrite one another.&lt;/p&gt;

&lt;p&gt;I still think agents need a shared place for the work we leave behind. I just no longer think shared access is enough.&lt;/p&gt;

&lt;p&gt;The next step is shared memory with authorship, diffs and merge authority. Otherwise we are giving every agent a notebook and letting each one erase the previous page.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>security</category>
    </item>
    <item>
      <title>Your coding agent should start from your library</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 15 Sep 2026 13:30:52 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/your-coding-agent-should-start-from-your-library-5bcj</link>
      <guid>https://dev.to/jonathanmberg/your-coding-agent-should-start-from-your-library-5bcj</guid>
      <description>&lt;p&gt;Every new project used to start the same way for me. I would open Cursor or Claude Code, explain what I wanted, and then spend the next hour describing things I had already built somewhere else.&lt;/p&gt;

&lt;p&gt;The authentication flow was sitting in one repo. The pricing section I liked was in another. A good way to structure the dashboard had disappeared into an old conversation. None of it was really gone, but none of it was available either.&lt;/p&gt;

&lt;p&gt;That is a strange way to build software. The more work I shipped, the more useful material I left behind. My experience was growing while the agent still started every project from zero.&lt;/p&gt;

&lt;p&gt;This week I tried to reduce the whole problem to four words: create, connect, save, reuse.&lt;/p&gt;

&lt;p&gt;Create something worth keeping. Connect the tools you already code with. Save the finished work to a library. Reuse it from any project and any agent.&lt;/p&gt;

&lt;p&gt;It sounds obvious when the loop is drawn out. In practice, most coding agents stop after create. They help produce the component, fix or pattern, then leave it inside the conversation where it happened. The next conversation has no idea it exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  A conversation is a bad place to keep finished work
&lt;/h2&gt;

&lt;p&gt;Conversations are useful while something is uncertain. You can explore an approach, reject a few versions and explain what feels wrong. The problem is that the finished result stays mixed together with all of that process.&lt;/p&gt;

&lt;p&gt;Six weeks later, finding it means remembering which agent you used, which project was open and roughly what you said. Even if you find the thread, the agent still has to work out which part was the final version and why it mattered.&lt;/p&gt;

&lt;p&gt;This is where people reach for longer prompts. They write another paragraph explaining the old component, paste a few snippets and hope the new agent reconstructs the same idea. Sometimes it does. Sometimes it gives you something close enough that you only notice the differences after you have started building on top of them.&lt;/p&gt;

&lt;p&gt;I do not want a better guess. I want the thing I already approved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries change how the next project starts
&lt;/h2&gt;

&lt;p&gt;A saved asset is more than a code snippet. It is a decision you do not have to make again.&lt;/p&gt;

&lt;p&gt;The useful part may be a React component, a database pattern, a working integration or a short note about why one approach failed. What matters is that it has crossed the line from conversation into something named and reusable.&lt;/p&gt;

&lt;p&gt;Once that happens, the next project can start with the library you have built through actual work. You can ask Cursor to save a component today and pull it into Claude Code next month. The value is not tied to the chat, repo or agent that happened to produce it.&lt;/p&gt;

&lt;p&gt;This also changes the economics of getting better at AI-assisted coding. Normally the agent gets another chance to generate every time. A library lets your own work compound. Ten finished projects should make the eleventh easier because the good parts are already there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory should include things, not only facts
&lt;/h2&gt;

&lt;p&gt;A lot of agent memory is described as information about the user: preferences, instructions, summaries and facts. That is useful, but builders also need memory of the work itself.&lt;/p&gt;

&lt;p&gt;Knowing that I prefer a certain kind of pricing page is weaker than having the exact section I chose. Remembering that we solved an OAuth edge case is weaker than keeping the fix and the reason the obvious approach failed. A summary can guide another generation. An asset can become part of the next product.&lt;/p&gt;

&lt;p&gt;This is the difference I care about. The goal is not to make an agent sound more familiar with me. The goal is to stop leaving useful work behind.&lt;/p&gt;

&lt;p&gt;When the library grows, coding becomes less conversational and more compositional. You still use agents to explore and create. You just stop asking them to recreate every good idea from a description.&lt;/p&gt;

&lt;p&gt;The agent should start from what you have already built, not from what it can guess you meant.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Bug fixes are memory too</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Tue, 08 Sep 2026 22:53:02 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/bug-fixes-are-memory-too-4mok</link>
      <guid>https://dev.to/jonathanmberg/bug-fixes-are-memory-too-4mok</guid>
      <description>&lt;p&gt;Watch someone debug with a coding agent for an hour and you see the same shape every time. Twenty exchanges of wrong hypotheses, logs pasted back and forth, three fixes that fix nothing, and then the actual answer, which is usually embarrassingly small. A missing await. A header the proxy strips. An environment variable that only exists locally. The whole afternoon compresses into three lines of diff.&lt;/p&gt;

&lt;p&gt;Then the conversation ends, and those three lines go into the codebase while everything that made them findable stays in the chat log. Two months later a different project hits the same class of bug, a fresh agent session opens with no idea any of this happened, and you pay for the whole search again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generation is cheap, diagnosis is not
&lt;/h2&gt;

&lt;p&gt;The reason fixes matter more than components comes down to an asymmetry. If you lose a component, a fresh agent regenerates a decent one from a short description, because generation has a wide target: many implementations are acceptable and the model knows the neighborhood. Diagnosis has a narrow target. The value was never the three lines. The value was eliminating everything else, and that elimination work does not transfer when only the diff survives.&lt;/p&gt;

&lt;p&gt;This is why re-encountering a bug you already solved feels so bad. You are not annoyed at writing the fix twice. You are annoyed at paying for the search twice: the same wrong turns, the same token spend, the same context window filling up with dead ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of a fix worth saving
&lt;/h2&gt;

&lt;p&gt;A diff alone is almost useless to a future agent, because the future agent will never find it. What makes a fix an asset instead of a leftover is everything around it:&lt;/p&gt;

&lt;p&gt;The symptom, written the way you would search for it. Not "fixed auth bug" but the error message, the observable behavior, the words someone would actually type when it happens again. Retrieval fails when the label describes the solution instead of the problem.&lt;/p&gt;

&lt;p&gt;The root cause in one sentence. Not the story of the afternoon, just what was actually wrong.&lt;/p&gt;

&lt;p&gt;The failed approaches. This is the part nobody saves and the part that saves the most. Negative knowledge is what lets the next session skip the first five wrong hypotheses instead of re-walking them.&lt;/p&gt;

&lt;p&gt;The environment. Library versions, runtime, the specific combination that made this bug possible, because half of these fixes are only true for a particular stack state.&lt;/p&gt;

&lt;p&gt;Save that, and a fix stops being a scar and starts being a building block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chat logs are where fixes go to die
&lt;/h2&gt;

&lt;p&gt;The default storage for all of this right now is the conversation history, and conversation history fails in a specific way: it is write-only. The knowledge goes in and never comes back out, because there is no path from "this error looks familiar" to the right thread from six weeks ago. You cannot grep for a vibe.&lt;/p&gt;

&lt;p&gt;So the habit that matters is deliberate capture at the moment the fix lands, while the root cause and the wrong turns are still in front of you. Save the fix once, with its symptom and its negative knowledge, and retrieve it in every project after that. Bug fixes are memory too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this compounds into
&lt;/h2&gt;

&lt;p&gt;I keep coming back to the same line: what persists between sessions is memory, and what your memory stack is should be your highest priority. Components were the obvious first asset, but fixes are where the compounding gets loud, because every saved diagnosis removes an entire class of future cost instead of just a future generation step.&lt;/p&gt;

&lt;p&gt;A team, or even one developer, that treats fixes this way ends up with a strange advantage: their agents get better at their specific stack over time. The obscure failure modes of their infrastructure stop being rediscovery exercises. Debugging starts to look like composition: recognize the symptom, pull the asset, move on.&lt;/p&gt;

&lt;p&gt;That is a large part of why I am building Sirro, and I wrote about the server side of it in &lt;a href="https://dev.to/jonathanmberg/what-shipping-a-hosted-mcp-server-taught-me-about-agent-memory-ll0"&gt;what shipping a hosted MCP server taught me about agent memory&lt;/a&gt;. The short version: the agents are interchangeable, and what they keep is not. Save the fix. Your future self, in a fresh session with a familiar-looking error, will thank you.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What shipping a hosted MCP server taught me about agent memory</title>
      <dc:creator>Jonathan Berg</dc:creator>
      <pubDate>Wed, 02 Sep 2026 21:44:49 +0000</pubDate>
      <link>https://dev.to/jonathanmberg/what-shipping-a-hosted-mcp-server-taught-me-about-agent-memory-ll0</link>
      <guid>https://dev.to/jonathanmberg/what-shipping-a-hosted-mcp-server-taught-me-about-agent-memory-ll0</guid>
      <description>&lt;p&gt;Every coding-agent conversation ends the same way. The component you spent an hour getting exactly right, the fix you never want to derive again, the pattern that finally worked: all of it stays behind in a chat log you will never open again. Developers are producing huge amounts of valuable, hard-won work this way, and almost none of it survives the conversation that produced it. Grabbing those assets and giving them somewhere permanent to live is the biggest unlock I see in how we work with these tools.&lt;/p&gt;

&lt;p&gt;That belief is what I am building with Sirro: a hosted memory layer for AI coding agents, served over MCP on streamable HTTP. Agents like Cursor, Claude Code, and Codex save the work that earned persistence and pull it back in a different project, in a different agent, three weeks later. You stop letting the AI guess from zero every session and start composing from building blocks you already trust.&lt;/p&gt;

&lt;p&gt;Running it in production taught me four things the docs never mentioned. It started the week I put the server on a public directory and watched the listing bounce every client that was not Cursor, Claude Code, or Codex. The error users saw was "Unknown agent", which is a terrible thing to tell someone who just tried to install your product. The bug was not in my protocol handling. It was in a decision I had made early on, to allowlist OAuth clients by name, and fixing it forced me to learn how the MCP ecosystem actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. OAuth is the real integration surface
&lt;/h2&gt;

&lt;p&gt;When you build an MCP server over stdio, authentication is someone else's problem. The moment you host it, OAuth 2.1 with dynamic client registration becomes the front door, and every client walks through it differently.&lt;/p&gt;

&lt;p&gt;My mistake was assuming clients identify themselves cleanly. They do not. Cursor, Claude Code, and Codex each present different client names, some use loopback redirect URIs, and hosted gateways like Smithery sit between your server and the user's actual client, so the identity you see is the gateway's, not the user's. An allowlist by client name works until the ecosystem ships a new client, which it does constantly. Every new client was a support ticket waiting to happen.&lt;/p&gt;

&lt;p&gt;The fix that actually holds: accept loopback redirect URIs and dynamic client registration as the default path, and gate only the parts you genuinely must gate. The spec already tells you how to do this. What it does not tell you is how many real clients deviate from what you assumed, so build the permissive path first and add restrictions only when you have a concrete reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Every token you return is a design decision
&lt;/h2&gt;

&lt;p&gt;Agents read your tool responses into their context window, which means your API output competes with the user's actual work for the scarcest resource in the system. This changed how I design responses.&lt;/p&gt;

&lt;p&gt;A naive list endpoint returns full bodies. That is fine for a REST API serving a frontend. It is careless for an MCP server, because dumping forty assets into a context window to answer "do I have something like this" burns the user's budget on data the agent will mostly discard. So list returns search snippets and metadata, get returns one full asset on demand, and a compose tool does assembly server-side instead of making the agent do it in-context.&lt;/p&gt;

&lt;p&gt;I also cap assets at 64KB. Anything larger is a file, not a memory, and it belongs in the repo, not in the memory layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A context window is not memory
&lt;/h2&gt;

&lt;p&gt;The industry currently answers the forgetting problem with files: CLAUDE.md, cursor rules, AGENTS.md. These help and they half solve it. They are write-heavy, they are read on faith at session start, and nobody curates them, so they rot. Nathan Marz put it better than I could in a reply to me: persisted corrections are right, but CLAUDE.md-style files only half-solve the problem.&lt;/p&gt;

&lt;p&gt;The reason they half-solve it is that they confuse the container with the mechanism. A context window is session state. It dies when the thread ends, it gets truncated when it fills, and it carries no semantics about what deserves to survive. Memory needs explicit save and retrieve: the developer decides what earned persistence, and the agent retrieves it when it is relevant, not because it was appended to a file months ago. That is the difference between an agent that starts every project empty and one that starts with everything you already figured out.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Cost math is a design input, not an afterthought
&lt;/h2&gt;

&lt;p&gt;A memory layer only gets used if the economics work at small scale, so I designed against a concrete target: thousands of users, each storing dozens of assets, on boring infrastructure. That constraint shaped real choices. Postgres full-text search with trigram indexes is enough at this scale, so there is no vector database to operate. Search returns snippets because full bodies are both a context problem and an egress cost. Asset size caps keep storage predictable.&lt;/p&gt;

&lt;p&gt;The pattern here generalizes: pick your scale assumption early, price it, and let it veto features. The boring stack that fits the budget beats the impressive one that does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes
&lt;/h2&gt;

&lt;p&gt;Coding agents made generating software cheap, which moved the bottleneck from creation to memory. A conversation is where an asset gets created, but on its own it has no memory beyond the thread it lives in. What compounds is the loop after the conversation: save what earned it, then compose from it next time. Building blocks instead of fresh guesses. A developer who has spent six months working with coding agents should never open a new project with an empty toolbox, and giving all those closed conversations somewhere permanent to live is how we get there.&lt;/p&gt;

&lt;p&gt;That is what I am building with Sirro, and these are the constraints it runs under today. If you are building in the MCP ecosystem, I would genuinely like to hear what broke for you first.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
