# Multi-player is more than multi-agent

Here **multi-player** means multiple humans or clients participating in shared work. **Multi-agent** means several model-driven workers. They can coexist, but adding workers does not solve shared-human authority.

Consider two clients attached to one session. Alice starts a change; Bob submits a conflicting instruction while Alice is approving a command. Which run receives Bob's input? Who may approve? Will both clients see the same event history? What happens if the approving client disconnects?

| Capability | Codex | pi | Goose |
| --- | --- | --- | --- |
| Shared observation | App-server tracks multiple subscribed connection IDs per thread and orders history attachment with notifications. | Chord and the experimental durable runtime provide snapshot/delta and conversation-view primitives. Coding-agent subprocess RPC is a separate surface. | The inspected ACP stream forwards updates to the prompting connection; generic fan-out was not established. |
| Input arbitration | Turn start can admit input to active work; explicit steering checks the expected turn. | The coding loop defines steering/follow-up queues. The adjacent replication libraries do not by themselves define a shared-human coding application. | A shared active-run registry rejects competing prompts and can route steering to the active owner. |
| Full multi-human workspace | Not established by these primitives. | Not established in the inspected coding-agent SDK/RPC. | Not established by these paths. |

Sources: [Codex subscriptions][c-clients] and [turn checks][c-steer], [pi RPC][p-rpc] and [durable views][p-views], [Goose shared registry][g-clients] and [notification forwarding][g-forward].

“Not established” is a scope limit, not an absence claim. Those three sets of code paths do not prove per-human identity, room membership, role-based approval, presence, collaborative file editing, or conflict resolution. A connection ID is not automatically a human identity.

**Design implication:** separate the session log from its audiences and writers. Define who can append input, control a run, grant permission, and receive tool output. Reconnection needs an ordering contract between the historical snapshot and live events; otherwise updates can be missed or duplicated.

## Sidekick: shared humans are an application boundary

Sidekick establishes a concrete shared-conversation surface. Access checks distinguish view, edit, and manage rights, including direct and group sharing. Sending requires edit access; submissions retain author identity and client-message IDs. Conversation locking decides whether input is placed or queued. These are application-level collaboration contracts beyond accepting multiple connections. [Access checks][s-access], [send admission][s-send] (private source).

Concurrent message writers obtain sequence numbers atomically. Reconnecting clients receive a state cursor and a queue high-water mark to reconcile snapshots with later updates. Persisted messages, transient streaming events, and authoritative turn rows still have different lifetimes. This supports shared observation and controlled writing; it does not establish collaborative file editing or one transactional event log. [Sequence allocation][s-seq], [queue reconciliation][s-queue], [state cursor][s-cursor].

[c-steer]: https://github.com/openai/codex/blob/8c076942cb70fba8e5c4732c23f1faabc4aed484/codex-rs/app-server/src/request_processors/turn_processor.rs#L1045-L1150
[c-clients]: https://github.com/openai/codex/blob/8c076942cb70fba8e5c4732c23f1faabc4aed484/codex-rs/app-server/src/thread_state.rs#L320-L687
[p-rpc]: https://github.com/earendil-works/pi/blob/482c1381a00d8d00bc81697e4a980c593db6803e/packages/coding-agent/docs/rpc.md#L1-L35
[p-views]: https://github.com/earendil-works/pi/blob/482c1381a00d8d00bc81697e4a980c593db6803e/packages/durable/src/harness/view.ts#L77-L177
[g-clients]: https://github.com/aaif-goose/goose/blob/34a222e3f2b95d8b4a43482b53c2cc957ecce26d/crates/goose/src/acp/server_factory.rs#L85-L233
[g-forward]: https://github.com/aaif-goose/goose/blob/34a222e3f2b95d8b4a43482b53c2cc957ecce26d/crates/goose/src/acp/server.rs#L2103-L2241

[s-access]: https://github.com/datex/sidekick/blob/463d653124e1c2cda46a3f14f01f3d6f384326b1/backend/src/sidekick/dependencies.py#L128-L187
[s-send]: https://github.com/datex/sidekick/blob/463d653124e1c2cda46a3f14f01f3d6f384326b1/backend/src/sidekick/routers/conversations.py#L2010-L2045
[s-seq]: https://github.com/datex/sidekick/blob/463d653124e1c2cda46a3f14f01f3d6f384326b1/backend/src/sidekick/services/session_dispatch.py#L92-L168
[s-queue]: https://github.com/datex/sidekick/blob/463d653124e1c2cda46a3f14f01f3d6f384326b1/backend/src/sidekick/services/message_queue.py#L420-L448
[s-cursor]: https://github.com/datex/sidekick/blob/463d653124e1c2cda46a3f14f01f3d6f384326b1/backend/src/sidekick/routers/conversations.py#L1278-L1285
