DEV Community

Open Human
Open Human

Posted on

治理的季节:开源复盘

Governance Season: An Open-Source Retrospective for MCP and Multi-Agent Memory

[02:03:12] sync start target=test-cluster

I keep that line pinned. Nothing in it looks like an emergency. The job had run every six hours for months — rsync pulling modules off a dev box into a working tree, --delete on, an exclusion list deciding what survived the pass. Then someone rebuilt that exclusion list, and a handful of entries didn't come through the edit. Not mangled. Absent. rsync doesn't ask why a path is missing from the list. Anything sitting on the target that wasn't excluded and wasn't arriving from the source got removed. Seventy-odd private modules gone in one run.

Getting them back was hand work: tracking down copies, diffing trees, pushing files back into place. Two hours and change of it, with people standing around a working directory nobody had thought of as load-bearing. The rebuild of the guardrails around that job took a lot longer than the recovery, and it came in pieces, across separate changes, none of which was right the first time.

What actually changed how I read agent stacks was this: every part of that failure was behaving correctly. rsync did precisely what rsync does. The list was internally consistent. The source tree was untouched. There was no broken node anywhere in the path. There was a set of nodes each acting on a picture of the world that nobody had verified end to end, and the deletion was the first moment the disagreement became visible.

That's the same shape I keep finding in MCP-driven multi-agent systems, and it's why open-source agent infrastructure is in governance season whether or not anyone wants it there. Unscoped MCP servers and shared long-term memory have quietly turned into incident surfaces. A single poisoned tool response, written into memory with nothing attached to say where it came from, becomes a belief that every downstream agent will act on in good faith. No agent in that chain does anything wrong. That's the problem.

The breakage keeps landing at the edges

Almost every incident I reviewed this quarter traced to a boundary rather than to model quality:

  • MCP servers shipping tools nobody scoped, including a couple that could reach environment secrets.
  • Agents writing tool output directly into long-term memory with no provenance attached to the write.
  • Planner and executor agents handing the same bad retrieval back and forth until the repetition starts to look like agreement.
  • Memory schemas that fork after a release, leaving two namespaces that each look authoritative and neither of which reconciles.

If your retrospective is a count of PRs landed and releases cut, you're measuring motion. Control is a different number, and it lives in the logs.

Who signs for this tool

The first thing we tried was documentation. Every MCP server adds a paragraph to its README describing what its tools do and what they're allowed to touch. Nobody read them, and two of the tools whose descriptions said they only read had write paths into the filesystem. A paragraph is not a boundary.

What replaced it: every server ships a signed capability file — tool names, input and output schemas, the scopes it claims, and an owner key on it. The build pipeline rejects unsigned files outright, and it rejects any tool asking for fs.write or net.egress where no owner is named. The signing step is where ownership stops being a vibe. If nobody will put a key on the tool, you've learned something more useful than the schema.

The cost is real. Onboarding a new server went from minutes to hours, and auto-updates stop working — a version bump now requires a person to re-sign before anything ships. For a production swarm, I'll pay that. I want a name to call at 3am, and I want it to be a person, not a repository.

Memory you can take back

Every write into shared long-term memory now carries agent_id, tool_call_id, source_hash, timestamp, and a confidence value. Scratch memory expires on its own and nobody worries about it. Long-term writes are propose-then-commit: a second agent recomputes the source hash, and only then does the write land.

Our first version was pure logging. We logged everything beautifully and had no way to use any of it. When a poisoned response surfaced later, the recovery plan was still "purge the namespace and rebuild from scratch," which is an admission that you don't know what's in there.

The hash is the index now. Roll back by source_hash, pull the writes that trace to one tool call, leave everything else standing. It costs an extra round trip on every long-term write, and conflicts that used to be smoothed over by last-write-wins now surface and have to be argued out. What you buy is the ability to surgically remove a belief instead of burning the store down.

When two agents disagree

Conflicting claims go to a small council: one maintainer seat, two agents from different roles. The council produces a single record, and the dissent stays in it.

First attempt was arbitration by the biggest model in the room. It sided with whoever wrote the longest justification, which is a very expensive way to find the loudest voice. The lesson was to keep the losing claim visible — that's usually where the early warning was sitting.

Decisions got slower. Somebody has to sit in the chair and read the disagreement instead of letting it resolve itself. That chair is the mechanism. Without it, the most confident agent overwrites the group and the group never notices.

It lives on a calendar

Governance in open source is a schedule, not a document. Four artifacts per quarter:

  • An incident ledger with an owner and a rollback path attached to every entry.
  • An RFC for any memory schema change, with a 72-hour comment window — no exemption for the person who wrote the schema.
  • Rotation of who holds the keys to the MCP registry, so no single maintainer becomes the permanent yes.
  • A public postmortem for any memory poisoning that crossed a namespace boundary.

We tried the soft version of this first: signing encouraged, warnings only. One release cycle later, everyone had learned to ignore the warning. The strict version holds so far, and I want to be honest that it hasn't been through a real crisis yet — the velocity cost is obvious today, the protection is theoretical until it isn't.

Back to that log line

The fix that came out of the sync incident had nothing to do with the exclusion list. Every run now does a dry pass first: the same rsync invocation with --dry-run, same flags, same paths. If the preview shows a file that exists on the target being removed, the run stops and the job is marked blocked. A human looks at it before anything is gone. That's the entire mechanism. It doesn't make the exclusion list correct. It makes a wrong exclusion list loud while it's still recoverable.

Run your quarterly pass the same way. Before anything writes into shared long-term memory, do the dry run: what would land, which tool call it traces back to, and which entries you'd be removing by hand if that tool turned out to be compromised. This is where I land, and I've been wrong about the timing of these things before — the tool layer and the memory layer are the two places where an agent stack either has an owner or doesn't, and everything else is downstream of that.

If you can't answer "who wrote this memory, from which tool, and how do we roll it back" from a log you can grep, you're not governing. You're hoping. MCP tools are signed capabilities. Multi-agent memory is an asset with a named owner. rsync --delete at least tells you what it's about to remove — your agent stack won't, unless you build the thing that makes it say so.

maref #ai #opensource #machinelearning

Top comments (0)