# QM: A Multiplayer Agent Harness With Per-Scope Sandboxes

> An open-source agent harness where every person and channel gets an isolated scope and sandbox, with a three-tier security posture and a swappable model core.

Published: 2026-08-02
URL: https://daniliants.com/insights/qm-a-multiplayer-agent-harness-with-per-scope-sandboxes/
Tags: multi-agent, sandboxing, agent-architecture, security

---

## Summary

QM is an open-source "multiplayer" agent harness meant for a whole company rather than one person. Every employee and every Slack channel or project gets its own isolated scope (memory, files, permissions, sandbox), while the underlying model and harness (Pi, OpenCode, Codex, Claude Code) is swappable behind a single core. The interesting part is not the pitch, it is the concrete architecture: per-scope durable sandboxes, a three-tier security posture, and two distinct patterns for deploying a customized fork without diverging from upstream.

## Key Insight

**Scoping model**

- Every person and every "room" (channel, group message, project) gets its own scoped memory, files, keychain view, permissions, crons, web apps, and a durable sandbox, rather than a shared context window with access control bolted on.
- Identity and config carry between Slack and the web app, so a person's agent configuration is consistent everywhere.

**Harness-agnostic core**

- Pi, OpenCode, Codex, and Claude Code all drive the same core loop, so the harness and model choice is a swappable substrate rather than something baked into the product.
- Architecture: Postgres holds sessions, memory, and queue; a headless core (API plus identity, policy, and scheduler, TypeScript on Node and Fastify) talks to the agent loop; a per-scope sandbox executes an `execute` tool, a small fixed tool surface rather than a sprawling toolset. Web UI, admin panel, portal, and Slack are all optional plugins over the core's HTTP API.

**Three-tier security posture (org-wide, scopes can only tighten it)**

- **Strict**: every tool call pauses for human approval except no-effect turn-enders.
- **Auto** (default): a classifier screens provenance-labelled external data and tool results before they reach the model, and deployments can point this at their own screening proxy.
- **Dangerous**: no screening, no pauses.
- A predeclared command policy (approval rules plus hard denials for things like recursive deletes or destructive SQL) applies in every posture, including Dangerous. The floor does not move.

**Two deployment patterns for customization without vendor lock or drift**

1. **Deployment directory**: `npm exec @yc-software/qm@latest -- qm init . --org <slug> --target <fly-or-aws>` scaffolds a repo that only depends on the qm package. Org-specific config, tools, and sandbox image live outside the core, with no source checkout needed.
2. **Private fork**: for orgs that want the whole codebase (core plus customizations) in one place for engineers and agents to read together, create it via a plain bare clone plus mirror push to a new private repo, never GitHub's Fork button. The reasoning given: a GitHub fork inherits the source repo's visibility (you cannot privatize a fork of a public repo), shares one object network (commits stay fetchable by SHA from the public side), and many orgs block forking private repos anyway. Org-specific code lives in `deploy/layers/<org>/` and core stays byte-identical to upstream, which keeps merges small. Two maintenance skills (`update-qm`, `upstream-pr`) handle pulling upstream in and pushing sanitized fixes back out, and the `upstream-pr` skill explicitly scrubs org identifiers from diffs, commit messages, and screenshots before it pushes.