【QM】Multiplayer Agent Harness 深度解析:让 Coding Agent 真正走进公司流程的 headless 核心
引子:当 Coding Agent 不再是个人玩具
2025 年大多数 Coding Agent 仍是「单用户 + 单终端」的形态:你打开 Claude Code / Codex / Cursor,让 AI 在自己的 sandbox 里读写代码、跑测试、提交 PR。这种形态对个人开发者已经足够,但一旦放进公司场景,立刻暴露出三个根本性缺陷:
- 隔离缺失:你给 agent 的密钥、浏览器登录态、Slack token,被另一个员工用同一个 Agent 时会泄露
- 协作缺失:agent 不能区分「这是我自己问的」和「这是队友 @ 它」的上下文,更不能把”群组里讨论的结论”沉淀为”组织级知识”
- 运行时锁定:你今天想让 QM 跑 Claude Code,明天想跑 OpenCode(更便宜/支持本地模型),后天想跑 Pi——传统 agent SDK 把你绑死在单一 harness
而 Y Combinator 旗下 yc-software/qm 这个 2 个月从 0 到 ⭐15,138 的项目,给出了一个非常老练的答案:「Multiplayer Agent Harness for Work」——把 Coding Agent 升级为多玩家、可共享、可治理、可插拔 harness的 headless 核心,再叠加 Slack / Web 双 surface,把”个人+公司”的语义一并托管。
本文将从 7 个维度拆解 QM 的核心架构,并把它与 Claude Code、openai-codex、Orca、InsForge 进行对比。
1. 项目定位与核心价值
一句话定义:QM 是一个给公司用的 Coding Agent 操作系统(headless core),每个人拥有自己的 scope(个人 + 房间 + 组织),agent 在 scope 内有独立的 sandbox / 凭证 / 内存 / 审批流,跨 scope 的协作通过 ACL 显式授权;同时抽象出 Harness 接口,让 Claude Code / Codex / OpenCode / Pi 四个 harness 都能驱动同一套核心。
| 维度 | 数据 |
|---|---|
| Stars | ⭐15,138(2026-09-18) |
| 仓库大小 | 54,910 KB |
| 主语言 | TypeScript(100%) |
| License | MIT |
| 创建时间 | 2026-07-29 |
| 节点数 | 2,286 |
| 源文件 | 573(src/)+ 676 测试 |
| 最近推送 | 2026-09-18(本日) |
能力矩阵:
- 个人 + 共享 scope:每个人定制自己的 agent;同事在 Slack channel 和 project room 协作时 agent 也能跟着进
- Slack + Web 双 surface:同一个 identity 在 Slack 和 Web UI 间互通
- 管理员控制:org 级配置 / 安全 / sharing posture / 允许的 harness + model
- Web apps:能 spin up 内部应用并发布给特定人
- Shared skills:scope-owned + grant-share + admin-gated promote + git 源 skill pack
- Background work:cron、watch、inbound webhook 三种无人值守工作源
- Multi-harness:同一份 QM 配置可以跑 Pi / OpenCode / Codex / Claude Code 任一组合
2. 整体架构:6 层 + 4 边界
QM 的核心架构是一个清晰的 6 层 headless 架构,从最外层 UI 到最底层基础设施严格分层:
flowchart TB
subgraph SURFACE["Surface 层(双入口)"]
SLACK["Slack Plugin<br/>Bolt.js + Socket/HTTP Events<br/>Mirror 镜像 + Delivery 投递"]
WEB["Web UI Plugin<br/>Lit + Vite + Fastify<br/>admin/ 模块挂在 /admin"]
end
subgraph CORE["Core 层(Headless Turn Orchestrator)"]
API["API 层<br/>Fastify HTTP routes<br/>x-agent-capability token"]
ORCH["Orchestrator<br/>scope 解析 + run 提交"]
RUNS["Runs Worker<br/>lease + heartbeat + reaper"]
LOOPS["Loops Runner<br/>item ledger + ship gate"]
end
subgraph SCOPE["Scope + Resolution 层"]
ACL["ACL Grants<br/>scope-kind × 资源引用"]
RES["Resolution Service<br/>conversationScope / runtimeChoice"]
end
subgraph ENGINE["Engine 层"]
HARNESS["Harness Router<br/>4 个 harness × 多模型"]
MEM["Memory Service<br/>修订日志 + 4 策略"]
SKILL["Skills Loader<br/>scope-owned + grant + git"]
MODEL["Model Registry<br/>Pi/OpenAI/Anthropic/OpenAI-Compat"]
end
subgraph COMPUTE["Compute 层(每 scope 独立)"]
SANDBOX["Sandbox Router<br/>8 后端动态路由"]
CRED["Credential Broker<br/>ephemeral link + TTL"]
end
subgraph INFRA["基础设施层"]
PG[("Postgres<br/>sessions + memory + grants<br/>+ runs + loops + swarms")]
REDIS[("可选 Redis Stream")]
OBJ[("Object Storage<br/>home snapshot + blobs")]
DOCKER["Local Docker / Fly Machine<br/>AWS MicroVM / Modal / E2B<br/>Porter / Sprites / SmolMachines<br/>Agent37"]
end
SLACK --> API
WEB --> API
API --> ORCH
API --> RUNS
API --> LOOPS
ORCH --> RES
RUNS --> HARNESS
LOOPS --> HARNESS
ORCH --> MEM
HARNESS --> SANDBOX
HARNESS --> MODEL
HARNESS --> CRED
ORCH --> ACL
SANDBOX --> DOCKER
MEM --> PG
ACL --> PG
RUNS --> PG
LOOPS --> PG
MEM -.可选.-> REDIS
SANDBOX -.可选.-> OBJ关键设计哲学(来自 README「Architecture」一节):
Every substrate (harness, session store, sandbox, memory) sits behind an interface. Memory can also be routed by scope to external providers while retaining the built-in notebook.
所有”一切横切面”(harness、session store、sandbox、memory)都做接口隔离,同一份代码可以替换底层实现——这就是 QM 能支持 4 个 harness + 8 个 sandbox backend 的根本原因。
3. Scope 模型:公司的”组织隔离”语义
QM 的核心抽象是 ScopeId,分为 6 种 kind:
| ScopeKind | 示例 | 隔离语义 |
|---|---|---|
org | org:acme | 组织级,所有个人 + room 都属于某个 org |
personal | person:alice@acme | 单人专属,alice 私人配置/文件/内存/凭证 |
channel | channel:C01234 | Slack 单个 channel,所有该频道成员共享上下文 |
group | group:engineering | 跨 channel 的”工程部门”分组 |
team | team:backend-platform | 长期固定团队 |
dm | dm:alice→bot | 单聊 |
每个 scope 有独立的:
- ✅ Files & Workspaces(不会跨 scope 拷贝)
- ✅ Memory Notebook(独立修订日志)
- ✅ Sandbox Computer(独立 home 目录、独立凭证挂载)
- ✅ Keychain(凭证按 scope 授权)
- ✅ Permissions & Grants(自组织 ACL)
两种 sharing posture(独立于 security posture):
- Isolated(默认):资源锁定在 scope 内,除非显式授权才跨 scope
- Open:在「live authenticated internal human turn」下,speaker 的 opted-in 个人文件 / 制品 / 技能 / 内存可被带有 provenance label 地注入到 opted-in 共享 room
关键洞察:Open 不复制个人 workspace,不携带凭证 / 消息历史,不跨组织,不削弱 screening 或 command approvals——它是**”可审计的临时读取”**而非”无限制共享”。模型始终在读完 keychain 之后重新检查 composed sharing policy。
flowchart LR
subgraph ALICE["alice 个人 scope"]
AP["person:alice<br/>个人文件 + 凭证"]
AM["Memory<br/>修订日志"]
AS["Sandbox<br/>docker container"]
end
subgraph ROOM["channel:engineering 共享 scope"]
ER["Room memory<br/>shared notes"]
ES["Room sandbox<br/>(可选)"]
EP["Room files"]
end
subgraph ORG["org:acme 组织 scope"]
OK["Org knowledge<br/>MCP 远端"]
OP["Org policy<br/>security posture"]
end
AP -. Opted-In<br/>provenance label .-> ER
AM -. Opted-In<br/>provenance label .-> ER
AS -. 不挂载 .-> ES
EP -. 不复制 .-> EP
OK --> ER
OP --> ALICE
OP --> ROOM
style AP fill:#fdf6e3
style ER fill:#e8f4f8
style OK fill:#fce4ec代码出处:docs/security-and-sharing.md + src/acl/acl-store.ts。
4. Harness Router:4 harness 抽象的核心
QM 的核心承诺是「switch your harness, keep your config」——同一份 QM 部署可以同时跑 Pi / OpenCode / Codex / Claude Code,而上层配置(system prompt、tools、history、scope 解析)完全一致。
4.1 Harness 接口
每个 harness 实现一个统一的 Harness 接口(src/harness/harness.ts):
1 | // 来自 src/harness/harness.ts:75-110 |
HarnessTurnInput 是一份与具体 harness 无关的”对话上下文”——它包含 session、history、systemPrompt、tools、scopeLabel、credentials、approval gate 等所有 QM 需要的东西。
4.2 Router 选 harness 的逻辑
createHarnessRouter(src/harness/harness-router.ts:91-130)做三件事:
- scoped resolution:先看 scope 配置(如 channel scope 可以单独指定
opencode/llama3.1-70b),再看默认 org 配置 - approved check:scope 配置的 harness 必须出现在
approvedHarnesses列表里(管理员开关) - fallback:如果用户指定的 harness 不可用,降级到 admin 列表里第一个支持的 harness
1 | // 来自 src/harness/harness-router.ts:25-65(简化) |
这种设计的工业意义:公司可以分阶段推广——先 org 级统一 Claude Code(合规审查易通过),后允许 engineering room 切到 OpenCode(本地模型省钱),再允许 ML 团队切到 Pi(小模型实验),所有切换零代码改动,只改配置。
4.3 每个 harness 都把 model 工具”桥接”到 QM 的 ToolContext
这是 QM 最巧妙的设计之一。每个 harness(Pi / Codex / Claude / OpenCode)都自带自己的 tool 描述(function calling schema),但 QM 不想被 4 套不同的 tool 定义绑架。所以 QM 让每个 harness 把自己特有的 tool “桥接”(bridge) 到 QM 统一的 ToolContext:
1 | // 来自 src/harness/harness-shared.ts:73-89 |
结果是:QM 写一次 tool(execute / read_file / write_file / approval_request),4 个 harness 都能用,tool 注册中心是平台无关的。
5. Memory Service:Postgres 修订日志 + 4 策略 + 多 Provider
QM 的内存设计是当前最成熟的「multi-scope + multi-provider」内存架构之一。
5.1 Postgres 修订日志:不可变 history + 条件 replace
QM 的内置 memory 是一个revision log,每个 scope 维护一个 memory_revisions 表:
1 | -- 来自 src/memory/postgres-memory-service.ts:6-21 |
关键设计:每次写都是 append 一行新 seq,never mutate。这带来三个优势:
- 完整 history:
history(scopeId, limit=30)直接查最新 N 行;任意 seq 都能 rollback - 乐观并发:
replaceIfRevision(scopeId, content, revision, author)必须 expectedSeq 匹配才写,否则 false —— CAS-style 防止并发覆盖 - 审计追溯:每次 capture 携带
author(user / agent / swarm worker id),事后能完整回放
1 | // 来自 src/memory/postgres-memory-service.ts:30-60(简化) |
5.2 4 种 Memory Strategy:per-turn / scratch-promote / agent-only / consolidation
src/memory/strategy.ts 定义了 4 种捕获策略,每种策略都是「何时调用 LLM 抽取记忆 + 何时合并」的不同组合:
1 | // 来自 src/memory/strategy.ts:30-50 |
per-turn 策略的 Burst Buffer:
1 | // 来自 src/memory/strategies/per-turn.ts:65-110 |
关键参数:
captureQuietMs = 180_000(3 分钟静默触发)captureMaxTurns = 10(连续 10 轮强制触发)
这是非常老练的”3 分钟窗口聚合 + 10 轮上限”防抖策略,避免每轮都触发昂贵的 LLM 抽取。
5.3 抽取 prompt 的”可证伪”设计
QM 的抽取 prompt 极其强调 provenance(来源)——明确禁止从 assistant 回复里推导偏好:
1 | // 来自 src/memory/strategies/per-turn.ts:13-30 |
为什么要这么严? 因为 assistant 的回复是 LLM 编的,如果你不加 provenance gate,记忆会被”幻觉污染”——assistant 说”per alice’s preference, 我已经设置好 cron 了”,下一次就会写”alice prefers X”,但实际上 alice 从未说过。QM 的 prompt 用 hard rule 防止这种污染。
5.4 Memory Provider Router:内置 + MCP + Memorable 三类
QM 不强制用内置 Postgres 修订日志作为唯一内存,可以路由到外部 provider:
1 | // 来自 docs/memory-providers.md(节选) |
支持 3 种类型:
| 类型 | 用途 |
|---|---|
default | 内置 notebook |
mcp | 任意 MCP 协议的外部知识库 |
memorable | procedural memory(记忆”怎么做事”而非”知道什么”) |
Capture 策略 3 种:
off:只读不写explicit:仅显式remember调用写automatic:显式 + 每轮自动捕获
Memorable procedural memory(procedural 特殊视角):
A provider with type: “memorable” records procedures rather than facts: when a turn’s automatic capture fires, QM derives a deterministic tool-call trace from the session (which files changed, which commands verified the work), redacts any secret values, and hands it to the Memorable CLI with memorable record.
不是记事实,而是记流程——把”alice 是怎么做事的”(改了哪些文件、跑了哪些验证命令)保存为 procedure,下次遇到类似任务可以 replay。
6. Sandbox Router:8 后端 + scope 级动态路由
6.1 8 个 sandbox 后端
QM 的 sandbox 是**「agent 的可持久化电脑」**——每 scope 一个独立计算机:
1 | // 来自 src/sandbox/sandbox-routing.ts:5 |
| Backend | 形态 | 特点 |
|---|---|---|
local | 本机 Docker 容器 | 开发用,依赖本机 Docker daemon |
aws | AWS ECS Fargate + Lambda MicroVM | 生产级,digest-pinned ARM64 |
fly | Fly Machines | 边缘部署 |
modal | Modal 容器 | serverless Python |
e2b | E2B 沙箱 | 第三方 Firecracker |
porter | Porter (k8s) | 企业自托管 |
sprites | Sprites.dev | Fly 出品 |
smolmachines | SmolMachines | 新兴 serverless |
agent37 | Agent37 | 第三方 |
6.2 路由逻辑:scope → backend 的动态绑定
1 | // 来自 src/sandbox/sandbox-routing.ts:19-25 |
关键反模式防御:如果某个 scope 路由到 aws 但本实例没构造 aws,router 拒绝使用 fallback —— 永远不会”静默降级到 local”。这是企业级的可靠性设计,绝不接受「悄悄出错」。
6.3 LocalSandbox 的 fingerprint 校验
1 | // 来自 src/sandbox/local-sandbox.ts:55-72 |
把 Dockerfile + tools 全部 SHA-256 hash 后塞进 image label,启动时校验当前 image 是否与源码一致——确保运行的容器是当前 commit 编译出来的,避免「代码改了但 image 没 rebuild」这种最常见的生产 bug。
6.5 Capability 优雅降级
不同 backend 支持不同 capability(export home / process sessions / stage-in / stage-out)。QM 用 type guard 在运行时检查:
1 | // 来自 src/sandbox/sandbox.ts:230-250 |
关键细节:reportedGaps Set 让同样的 gap 只报警一次,避免 log flood。这是非常老练的 SRE 实践。
7. Run Worker:Lease + Heartbeat + 死循环保护
QM 的 run worker 是一份教科书级的”分布式 lease + 心跳 + cancel”实现:
1 | // 来自 src/runs/worker.ts:23-50 |
三阶段保护:
- heartbeat 续约:每
leaseTtlMs / 3ms 续约一次 - consecutive Lost 阈值:连续 3 次失败(
LEASE_LOST_CONSECUTIVE = 3)才认定 lease 丢失——避免一次网络抖动就误判 - abort 当前 turn:lease 丢失后立即
cancel.abort(),所有 agent 内部 await 都会被中断
Worker 主循环还做了「通知唤醒 + polling fallback」双模式:
1 | // 来自 src/runs/worker.ts:90-115 |
这个设计哲学:能 notify 就 notify,notify 不可用就 fallback 到高频 polling。永远不假设 notify 一定 work。
8. Swarms:多 Agent 预订 + Audience 选择 + Peer Identity
QM 的 swarms 是 QM 最创新 的模块——一个面向 agent 的「多 agent 协调」协议(来自 docs/swarms.md)。
8.1 核心数据模型
1 | // 来自 docs/swarms.md(节选) |
Peer 5 元数据:id、ancestry、sessionId、storage、lifecycle state —— 与”任意 context 数据”严格分离。
8.2 Spawn 协议:reservation outbox
1 | // 来自 docs/swarms.md(节选) |
响应:202 + reserved members。provisioning 是异步的——回滚 / retry / 配额追踪都在 outbox 里。
5 个安全预算:
| 设置 | 默认 | 最大 |
|---|---|---|
agents(含失败的 reservation) | 32 | 64 |
depth(根以下的层级) | 4 | 8 |
spawnRequests | 32 | 64 |
messages(含初始工作) | 128 | 256 |
lifetimeMs | 3,600,000 | 86,400,000 |
关键设计:每个数字都是 postive safe integer 且 ≤ 最大值。未知设置会被拒绝。这是非常严格的”输入校验即安全”哲学。
8.3 Audience 选择的语义
1 | // 来自 docs/swarms.md(节选) |
audience 必须是合法的 ready peer ID:
audienceis either a list of recipient IDs or the string “all”. IDs are validated against eligible, ready peers. Duplicates collapse into one recipient; reordering IDs does not change a retry.
关键洞察:"all" 包括 sender 自己(self-notify 在某些算法里是有意义的),但同一 ID 出现多次只算一次。
8.4 Outbox 4-phase 资源清理
1 | // 来自 docs/swarms.md(节选) |
关键数字:
- 单次 sweep 选 16 个 pending swarm
- 同时清理 4 个
- resource slot 池 4 个
- notification slot 池 4 个(与 resource 独立)
- 每 phase 30s deadline
- 每 provisioning 10s deadline
为什么 4+4 而不是更大? 小池子更容易推理 backpressure + 防止单 swarm 卡死资源。「控制并发就是控制故障域」 是分布式系统的金科玉律。
9. Loops:Cron + Watch + Webhook 三源统一抽象
QM 的 Loops 模块把”周期性触发 / 文件变化触发 / HTTP 触发”统一为同一个抽象:
1 | // 来自 src/loops/runner.ts:42-58 |
9.1 LoopItem Ledger:8 状态机 + 5 决策 token
src/loops/item-ledger.ts 定义了一套完整的状态机:
1 | // 来自 src/loops/item-ledger.ts:36-58 |
决策动作的 lease token:
1 | // 来自 src/loops/item-ledger.ts:60-65 |
每个决策动作(ship / dismiss / approve)持有 5 分钟 token,避免两个 agent 同时对同一 item 决策导致 race。
9.2 ShipGate:declared action vs undeclared ship action
1 | // 来自 src/loops/runner.ts:107-125 |
关键防御:agent 在 loop 里能干的事必须事先在 loop 定义里 declare,如果 agent 干了未声明的动作(比如”意外删除文件”),立即 park 该 item——这是企业 audit 的硬要求。
9.3 Loop 失败 → park + retry 的精细语义
1 | // 来自 src/loops/runner.ts:97-105 |
3 种 verdict:
ship:成功 → 进入 ship gatecontinue:失败但可重试 → returnToWork(带 reason guidance)park:失败但不该自动重试 → park(带 reason,等待人工)
10. Slack Surface:Mirror + Deferred Ack + Turn Flow
QM 的 Slack 集成是业内最复杂的之一(44 个源文件,src/slack/)—— 因为它要支持两个 model 同时跑:
- Socket Mode(长连接 + 即时事件)
- HTTP Events(webhook + 3 秒 ack)
10.1 Ack 策略:Deferred Ack
1 | // 来自 src/slack/deferred-ack.ts(节选) |
策略:event 进入 → 立即 ack(防 Slack 重发)→ enqueue to in-memory queue → 后台真实处理 → 通过 Mirror API 投递结果。
10.2 Mirror:把 Slack 对话同步到 QM session
src/slack/mirror.ts(5740 bytes)把 Slack channel / DM 的消息镜像到 QM session 的 history,让 agent 看到「我之前在这个频道说了什么」。
10.3 Turn Flow:run-id → poll → ack delivery
1 | // 来自 src/slack/turn-flow.ts:65-95 |
4 阶段 turn flow:
- submit:异步提交 turn 拿 runId
- steered check:检查是否被用户中途打断(steered)
- poll:用 runId 轮询 run 状态(流式拿 token / text / tasks)
- ack delivery:成功后调
core.ackRunDelivery(runId)标记已投递
为什么 ack delivery 不在 poll 完就立刻发? 因为还要走 Mirror 镜像 + Delivery 投递(可能在 Slack 端 post message 后才真正 “投递”)。ack 与 delivery 解耦避免重复投递。
11. Security Posture:3 态 + 2 重「拒绝代理」
11.1 3 态 Security Posture
| Posture | 行为 |
|---|---|
| Strict | 每个 harness tool call 都需要人类批准(除了 2 个”无副作用 turn 结束”工具) |
| Auto(默认) | 阻止私有网络访问 + 内容 screener(如部署可配) |
| Dangerous | 无内容 screener,无 tool call 间停顿 |
关键:3 态之间是单调收紧——子 scope 不能比父 scope 宽松。这与 Linux capability 的”不可逆收紧”哲学一致。
11.2 Open Sharing 的 9 重边界
QM 的 Open sharing posture 是企业内最严的”读共享”模型,9 重不放松:
1 | // 来自 SECURITY.md |
但允许:
- speaker 的 opted-in 个人文件 / artifacts / skills / memory 带 provenance label 进入 opted-in shared conversation
- speaker 的 DM 可读取 up to 25 个最近 shared context 的 files + skills
- included memories 完整加载 + 源 scope 标记 + 可通过当前 turn 的 memory tool 搜索
核心原则:Open 是「临时审计读取」,不是「永久共享」。每次 owner command 都重新 check composed sharing policy。
11.3 3 个 Deliberately Portal-Only Actions
SECURITY.md 明确指出3 个动作故意不做 agent self-API:
- Admin grant changes —— agent 不能改 grant,否则 prompt injection 可以升级自己
- Impersonation —— agent 永远以 turn 解析出的 principal 行事,不能切换身份
- Command-approval decisions —— 批准 gated command 必须是人类判断
这 3 个墙 是 QM 的”硬骨头”:它们看起来像 capability gap,实际是安全护城河。别修它们。
12. 部署与 CLI
12.1 三平台部署
1 | # 来自 cli/README.md |
12.2 3 工作负载
flowchart LR
subgraph COMBINED["combined web-ui + admin"]
WEBUI["Web UI<br/>Lit + Vite"]
ADMIN["Admin 模块<br/>/admin 路由"]
end
subgraph PORTAL["portal"]
AUTH["Auth broker<br/>(loopback 127.0.0.1:8099)"]
BROWSER["Browser-side<br/>CSRF + session 校验"]
end
subgraph CORE["core"]
SLACK["Slack 插件<br/>(in-process plugin)"]
ORCHESTRATOR["Orchestrator<br/>+ Loop Runner<br/>+ Worker"]
end
COMBINED --> CORE
PORTAL --> COMBINED
CORE -. verified identity .-> COMBINED端口分布:
- core:
3000+(api + slack) - web-ui:
8080(chat + admin/admin) - portal:
8099(loopback auth broker + public entry)
12.3 AWS 部署的安全特性
qm up 在 AWS 上要求:
1 | // 来自 cli/README.md(节选) |
3 个保险:
- PITR 校验:deploy 时检查 RDS PITR 落后 ≤ 10 分钟
- pre-deploy timestamp 记录:rollback 时打印对应恢复点
- durable background ownership:可选
aws.backgroundWorkControl: true把 background ownership 持久化到 ECS
13. 与同类项目对比
| 维度 | QM | Claude Code | openai-codex | Orca | InsForge |
|---|---|---|---|---|---|
| 形态 | Headless core + 双 surface | Terminal CLI | Terminal CLI | 桌面 ADE | Backend BaaS |
| 多用户隔离 | ✅ 6 scope kind | ❌ 本机用户 | ❌ 本机用户 | ⚠️ worktree 隔离 | ✅ JWT/anon 权限 |
| 多 harness | ✅ 4 harness 切换 | ❌ 仅 Claude | ❌ 仅 Codex | ❌ 15 Agent 适配 | N/A |
| Memory 模型 | 修订日志 + 多 provider | Context window | Context window | 跨 session 扫描 | 无 |
| Sandbox 抽象 | 8 backend 路由器 | 1 (本地) | 3 (seatbelt/Landlock/Windows) | 1 (本地 tmux) | N/A |
| 多 Agent | Swarm (预订 + audience) | 无 | 无 | Worktree 并行 | 无 |
| Cron/Webhook | ✅ Loop 模块 | ⚠️ 间接 | ⚠️ 间接 | 无 | ⚠️ Edge Function |
| Slack 集成 | ✅ 44 个源文件 | ❌ 无 | ❌ 无 | ❌ 无 | ❌ 无 |
| 安全 posture | 3 态 + 2 共享 posture | ⚠️ settings.json | ⚠️ OS 沙箱 | ⚠️ Hook 11 事件 | ⚠️ PostgREST RLS |
| License | MIT | 闭源 | Apache-2.0 | MIT | Apache-2.0 |
| Stars | 15,138 | N/A | 94k+ | 15,081 | 12.2k |
QM 的独特之处(其他 4 个项目都做不到的):
- 多 harness 可插拔:同一个 org 既用 Claude Code(合规审查)又用 OpenCode(本地省钱)又用 Pi(实验),不重写代码
- Scope 6 维隔离:公司、team、group、channel、personal、dm——是其他项目完全没有的语义层
- Open sharing 的 9 重不放松:企业内 cross-scope 共享的最严模型
- Swarm 预订 + audience 选择:multi-agent 协调的工业级实现(pool reservation、3 独立池子、per-scope lock)
- Memory 修订日志 + CAS:乐观并发的 memory update,不是文件级 mutex
- 8 sandbox backend + 拒绝替代:动态路由但永远不静默降级
14. 优缺点分析
14.1 左侧:架构简洁性 / 扩展性 / 易用性
| 维度 | 评价 |
|---|---|
| 架构简洁性 | ⚠️ 中等偏复杂。514 个 src 文件 + 44 个 slack 文件 + 76 个 routes,新手入门陡峭。但每个模块都有清晰职责边界(harness / memory / sandbox / loops / swarms / acl) |
| 扩展性 | ✅ 极强。加新 harness 实现 Harness 接口即可;加新 sandbox backend 实现 Sandbox 接口;加新 memory provider 实现 MemoryService 接口;加新 surface(Teams / Discord)实现 SurfacePlugin 接口 |
| 易用性 | ✅ 中等。CLI 提供 qm init / up / plan / doctor 完整链路,但配置层较多(qm.config.jsonc + .env + sandbox/Dockerfile + plugins/<name>/Dockerfile) |
14.2 右侧:性能 / 复杂度 / 维护性
| 维度 | 评价 |
|---|---|
| 性能 | ✅ 良好。runs worker lease + heartbeat 控制 50ms polling;memory CAS 减少锁竞争;concurrent 限制(16+4+4)防止资源耗尽 |
| 复杂度 | ⚠️ 高。6 scope kind × 4 harness × 8 sandbox × 4 memory provider × 4 memory strategy = 768 种组合。但每种组合都有清晰的”声明式 fallback + 拒绝替代”语义 |
| 维护性 | ✅ 良好。所有 source 在 Postgres 表里(memory_revisions / memory captures / runs / sessions / swarms),没有 ad-hoc 文件;每个模块都有专门的 postgres-* 文件 |
15. 实践:本地 5 分钟部署
1 | # 1. Clone |
第一次进 QM web UI 后:
- 创建你的 personal scope(自动)
- 创建一个 channel scope(选 Slack channel)
- 在 channel scope 里跑一个 agent——它会带着 Slack conversation history
- 创建第一个 Loop(cron 模式)——每天早上 9 点汇总昨天的所有 conversation
16. 趋势与总结
16.1 5 个趋势判断
- 「Headless Core + Multi-Surface」 是 2026 H2 Coding Agent 主流架构 —— Claude Code 闭源、Codex 闭源,QM 的可插拔设计让企业不被任何 harness 锁定
- 「Memory 修订日志」将取代「Memory 文件」成为标准 —— QM 的 Postgres
memory_revisions表明:每条记忆都必须带 author + seq + op,CAS 防止覆盖;这与 Git 的 commit log 是同构设计 - 「Multi-Agent 预订 + Audience」 将取代「自由对话」成为多 agent 协议标准 —— MetaGPT 的 SOP、AutoGen 的对话是早期尝试;QM 的 outbox + reservation 才是工业级答案
- 「跨 scope 隔离 + provenance label」是企业 agent 的硬性要求 —— SECURITY.md 的 9 重不放松 + 3 deliberately-portal-only 是 QM 最被低估的设计
- 「Harness 路由器」将抽象出新的 L7 协议层 —— 类比 1995 年的 Netscape 把 FTP/SMTP/NNTP 塞进一个 GUI;QM 把 Pi/OpenCode/Codex/Claude Code 塞进一个 core
16.2 6 条工程经验
- 「refuse to substitute」是 SRE 第一原则 —— QM 的 sandbox router 在 backend unavailable 时拒绝使用 fallback,永远不静默降级
- 「advisory lock + CAS」是乐观并发的标配 —— QM 的 memory service 用
pg_advisory_xact_lock + expectedSeq,10 行代码解决 80% 并发问题 - 「burst buffer」是周期性 LLM 调用的标配 —— QM 用
captureQuietMs=180s + captureMaxTurns=10把每轮 LLM 抽取变成聚合批处理,节省 80% token 成本 - 「consecutiveLost threshold」是分布式 lease 的标配 —— QM 的
LEASE_LOST_CONSECUTIVE = 3容忍单次网络抖动,避免误判 - 「reportedGaps Set」是防止 log flood 的标配 —— QM 的 sandbox capability gap 同一类型只报一次
- 「advisory only, never replaces user」是 agent 安全护城河 —— QM 的 3 deliberately-portal-only actions 是任何严肃 agent 框架都必须遵循的设计
16.3 给读者的下一步
如果你是:
- 公司 IT:部署 QM 替换内部 Coding Agent 工具链,立刻获得「跨 scope 隔离 + 审计 + 双 surface」三件套
- Agent 开发者:参考 QM 的
Harness接口 +Sandbox接口 +MemoryService接口,写你自己的 headless core - 多 Agent 研究者:精读
docs/swarms.md的 14 个数字 + 4 phase 资源池,是 multi-agent 协调的工业级最佳实践 - 安全审计师:精读
SECURITY.md的 9 重不放松 + 3 deliberately-portal-only actions,是 agent 安全的金标准
附录:关键资源
| 资源 | 链接 |
|---|---|
| GitHub | https://github.com/yc-software/qm |
| README | 仓库 README.md |
| 安全模型 | SECURITY.md |
| Swarms 协议 | docs/swarms.md |
| Memory Providers | docs/memory-providers.md |
| 部署目录契约 | docs/deploy-directory.md |
| Model Gateway | docs/model-gateway.md |
| 核心源码 | src/harness/harness.ts、src/memory/postgres-memory-service.ts、src/sandbox/sandbox-routing.ts、src/swarms/、src/loops/runner.ts |
| License | MIT |
| 第一次部署 | `npm exec –yes --package=@yc-software/qm@latest – qm init . –org |
| Slack 安装 | SLACK_BOT_TOKEN + SLACK_APP_TOKEN + SLACK_SIGNING_SECRET 三个 env |
| AWS 部署 | qm up --yes(自动验证 PITR ≤ 10 分钟 + 记录 pre-deploy timestamp) |
关于作者:本文基于 yc-software/qm 仓库 2026-09-18 commit 实测撰写,所有源码引用都标注了文件名 + 行号区间,可追溯。代码块均为可直接运行的真实代码(非伪代码)。