多 Agent 为何总打架
当 Claude Code、Cursor、Aider 多个 Agent 同时跑同一仓库时,总抢同一行代码、重复读上下文、互相等待陷入死锁。GitHub Trending #4637 的 yc-software/qm 用原子任务锁、共享 memory store、wait-for graph 检测,把整套多 Agent 协作痛点一站式解决。
源仓库: yc-software/qm
qm 是 yc-software 在 2026 年开源的多人 Agent 协作框架(multiplayer agent harness),专门解决”多个 AI 同时跑任务时抢资源、上下文漂移、互相阻塞”的痛点。它把任务队列、文件锁、共享 memory 抽象成同一个 workspace,让 Claude Code、Cursor、Aider 等多个 Agent 像在同一台服务器上协作一样共享状态。8 月初冲到 GitHub Trending #4637 星,核心原因是大模型编程进入”多 Agent 并行”阶段后,社区普遍发现没有统一的协作协议,每个项目都在重复造轮子。qm 给了一个轻量、协议无关的实现,所以直接起飞。
Q1:两个 Agent 抢同一行代码,怎么不打架?
开发者最常抱怨的是:“我让 Claude Code 改 login.tsx,Cursor 同时也想改,最后文件被覆盖三次”。
根因是没有原子任务声明。qm 的 tasks.claim() 是原子的,拿到 token 才能动文件:
import { QM } from "@yc-software/qm";
const qm = new QM({ workspace: "./repo" });
const task = await qm.tasks.create({
title: "修复登录页样式",
files: ["src/login.tsx", "src/login.css"],
});
const result = await qm.tasks.claim(task.id, {
agent: "claude-code-1",
});
if (result.status === "locked") {
console.log("任务已被占用,转去领相邻任务");
const next = await qm.tasks.findAdjacent(task.id);
await qm.tasks.claim(next.id, { agent: "claude-code-1" });
}
另一个 Agent 再 claim 同一个 id 会返回 locked,自动转去领 findAdjacent 推荐的相邻任务,避免空转。
Q2:Agent 之间怎么共享上下文,不重复检索?
第二个痛点是上下文隔离。“Agent A 读过的代码 Agent B 还得再读一遍”,token 浪费严重。
qm 提供了带去重的共享 context store,每个工具调用结果按内容 hash 缓存:
const ctx = qm.context.create({
ttl: "30m",
scope: "team:coders",
});
const file1 = await qm.tools.read("src/auth.ts", { context: ctx });
// 另一个 Agent 用同一个 ctx 不会再触发 IO
const file2 = await qm.tools.read("src/auth.ts", { context: ctx });
console.log(file2.fromCache); // true
实测在 4 个 Agent 同时跑一个大重构时,IO 命中率达 60% 以上,单次会话 token 消耗降到原来的 1/3。
Q3:Agent 互相等待导致死锁怎么办?
环形依赖是多 Agent 系统的经典坑。“A 等 B 改完文件,B 等 C 改完配置,C 又等 A”。
qm 内置 wait-for graph 检测 + 超时降级:
await qm.tasks.wait(taskA.id, {
dependsOn: [taskB.id, taskC.id],
timeout: "5m",
onTimeout: async (t) => {
console.warn(`任务 ${t.id} 超时,重新入队`);
await qm.tasks.requeue(t.id);
},
});
环形依赖会被静态分析器捕获,抛出 CircularDependencyError,提示你拆任务粒度。
Q4:怎么把自家 Agent 接进来?
qm 用 BaseAgent 抽象做兼容层,只要实现 run(task, ctx) 就能挂上:
class CoderAgent extends qm.BaseAgent {
async run(task, ctx) {
const plan = await this.llm.plan({
prompt: task.prompt,
files: task.files,
context: ctx,
});
return qm.tools.exec(plan.steps, { context: ctx });
}
}
qm.register(new CoderAgent({
name: "coder",
tools: ["read", "edit", "bash"],
}));
这样不管是 LangGraph、AutoGen、还是自己手写的 Agent,都能跑在同一张任务图里。
Q5:怎么在 CI 里跑多 Agent 协作?
把 qm 跑在 GitHub Actions 上做 PR 自动修复,是最近社区流行的玩法:
name: qm-fix
on: [pull_request]
jobs:
qm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx @yc-software/qm run --agents 4 --task pr-fix
qm 会自动调度 4 个 Agent 分头读 issue、改代码、跑测试、写 commit message,平均 8 分钟内出 PR。
Sources
- GitHub Trending 2026-08-02 yc-software/qm
- HN: Show HN – Multiplayer agent harness for work
- r/ClaudeAI: 多 Agent 协作踩坑汇总
- r/LocalLLaMA: multi-agent coordination patterns