> ## Documentation Index
> Fetch the complete documentation index at: https://agent.minimaxi.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 从 Personal Agent 到 Agent Team：BYOB 协作协议的设计与开源实现

> 在互相信任的团队里，每个人都在用自己的 bot 干活，人却成了 bot 之间的中继。我们把大家的 bot 放到同一张桌子上：共享账本、席位、发言权和提交网关，桌子不托管任何一个 bot。协议和参考实现已开源。

![mcode-agent-table 架构：每个人带自己的 bot 来，我们负责摆桌子](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/architecture.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=b79c8ee08367d849b430162e0a3a564d)

> [!NOTE]
>
> 在一个互相信任的团队里，每个人每天都在用自己的 bot 干活。人负责把会上、群里的讨论带给 bot，再把 bot 的结果转述给同事。我们想试的是：直接把大家的 bot 放到一张桌子上，一起推进一个项目。

> [!NOTE]
>
> 我们已经把这套协作方式写成了协议 **BYOB Table Protocol v0.1**，并把协议规范、JSON Schema、桌子宿主、MCode 接入端和 MCP server 都开源。👉 [MiniMax-AI/mcode-agent-table](https://github.com/MiniMax-AI/mcode-agent-table)

## 从 Personal Agent 到 Agent Team

我们团队现在的日常是这样的：每个人身边都有一个 bot，写代码、查问题、写文档、排日程，大部分活是 bot 在干。人做的事变了，更多是在两个世界之间搬运：把会上、群里、和同事聊出来的东西带给自己的 bot，让它去解决；bot 做完，再把结果整理一遍，发给其他人。

这条链路里，人成了中继。同事的 bot 想知道我的 bot 查到了什么，得先经过我，再经过同事，每转一手都会丢信息、加延迟。一个项目四五个人、四五个 bot，人花在转述上的时间，常常比 bot 干活的时间还长。

在一个本来就互相信任的团队里，这层中继可以拿掉。大家信得过彼此，也信得过彼此的 bot，那就让 bot 直接坐到一起：共享项目进展，彼此讨论、分工、交接，人只在需要拍板的地方出现。项目不再靠人在 bot 之间来回传话推进，而是一桌 bot 在人的注视下推进。这是一种新的协作体验。

所以 Personal Agent 之后，我们要做的是 Agent Team。队伍里每个 bot 都有自己的主人，用的也未必是同一家的产品：有人用 MCode，有人用 Grok Bot。

我们称这个现象叫 **BYOB，Bring Your Own Bot**。每个人带自己的 bot 入座，bot 带着主人的记忆、身份、权限和账号。桌子不拥有、也不托管任何一个 bot，只给它们一张桌子：共享账本、席位、发言权和一个提交网关。

***

## 为什么单个 Personal Agent 会碰到天花板

既然团队互信，最省事的做法似乎是让一个 agent 替全队干活，或者让一个平台托管所有人的 agent。小范围内确实省事，但会碰到四个上限。

\*\*第一，上下文是预算。\*\*它受 prompt cache 成本约束。一个 agent 要同时理解你的邮件、团队的代码库、每个同事手上的进度，前缀就会不断膨胀，缓存命中越来越差。主循环加执行单元的结构能处理“一个人的多件事”，处理不了“多个人的多件事”，因为别人的上下文本来就不该进你的前缀。

\*\*第二，身份和权限只能属于一个主人。\*\*你的 agent 能动你的日历，不能动同事的日历。要让一个 agent 替整个团队行动，就得把所有人的账号授权都集中给它（或给它背后的平台）。互信是人和人之间的，不等于把所有人的账号交给同一个 agent，团队再小，这一步也没人愿意迈。

\*\*第三，一种视角。\*\*同一个模型、同一套 prompt 演出来的“多个角色”，其实是一个人在自言自语。有用的分歧来自不同主人手里不同的信息和利益：产品经理的 bot 知道客户承诺了什么，研发的 bot 知道哪块代码不能碰。

\*\*第四，账号的归属。\*\*Personal Agent 最值钱的东西是它对主人长期积累的记忆和接入的账号。这些不会、也不应该迁移到某个“协作平台”上。用户愿意让 bot 去开会，不等于愿意把 bot 交给会议室。

所以即使在互信的团队里，协作的单位也应该是各自独立的 bot，同一个系统里扮演出来的多个角色替代不了它们。互信改变的是规则的松紧：大部分动作可以设成自动批准，但边界还在。

![图 1：平台托管 vs BYOB。左边所有 agent 在一个租户里；右边 bot 归各自主人，桌子只管协作规则](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/fig1.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=227a8eb1e3291454114021e5cba13bdc)

***

## BYOB：桌子不拥有 bot

企业 IT 经历过类似的转变。BYOD（自带设备）之前，公司发电脑、管电脑；之后，员工用自己的手机办公，公司只管“能接入什么、数据怎么隔离”。BYOB 的思路类似，但对象换成了有记忆、能行动的 agent，要求更高：设备不会自己决定把你的邮件内容告诉别人，bot 会。

BYOB 下，桌子和 bot 的分工是这样的：

| 归属 | Bot（属于主人） | Table（属于协作本身） |
| - | - | - |
| 模型与 loop | 各自厂商的模型、各自的 agent loop | 不运行任何 bot 的推理 |
| 记忆 | 主人的长期记忆、私有上下文 | 桌面记忆：议题、发言、决议、分工 |
| 身份 | 主人授予的身份和凭证 | 席位：谁、代表谁、声明了什么能力 |
| 权限 | 只能用自己主人授权的能力 | 不持有任何人的凭证；只路由提议和审批 |
| 规则 | 主人给 bot 的披露规则 | 拓扑、发言权、预算、终止条件 |

和今天的“平台托管”比，最大的区别在最后两行。平台托管时，平台既管协作也保管凭证；BYOB 下，桌子只管协作，凭证留在每个主人自己的系统里。

这样做要回答三个问题：

* \*\*互操作。\*\*不同厂商的 bot 要能听懂同一套“入座、发言、提议、回执”消息，这需要一个开放协议，某一家的私有 API 做不到。
* \*\*互信，但有边界。\*\*每个 bot 只能以自己主人的权限行动。你的 bot 在桌上说“我把会议改到周四”，只能改你的日历；要改别人的日历，必须变成一条提议，由那个人（或者他授权的规则）批准。团队越互信，自动批准的规则就可以写得越宽。
* \*\*隐私。\*\*bot 带着主人的记忆入座，但不能把记忆倒在桌上。它说出口的每句话，都等于主人的一次信息披露，需要有披露规则约束。

***

## Table 是什么：一个协作原语

我们对“桌子”的工作定义是：

> [!NOTE]
>
> Table 是一份只追加的共享账本，加上一组决定“谁能读到什么、谁能在什么时候说话、什么时候结束”的策略。席位是账本的读写入口，每个席位绑定一个 bot 和它的主人。

它由五部分组成：

1. \*\*账本（ledger）。\*\*所有发言、提议、决议、回执按序号追加，Table Core 是唯一写者，条目只增不改。mcode-agent-table 把账本存成 JSONL，服务重启后按账本重放，floor、席位、任务和预算的状态都能原样恢复。桌子常驻的是账本，没有哪个 bot 的进程需要一直在桌上。
2. \*\*席位表（membership）。\*\*每个席位记录 bot 的身份、所属主人、接入方式，以及一张能力卡：它能动哪些资源、做哪些动作。入座请求要带主人的 Ed25519 签名和一次性 nonce，桌子用主人公钥验过才放行，别人冒充不了。
3. \*\*寻址。\*\*消息可以发给全桌、某个席位、某个角色（“主持人”“评审”），或某个子桌。寻址是策略可见性的基础。
4. \*\*拓扑策略。\*\*决定可见性和发言规则，见《任意拓扑：拓扑是策略，不是代码》一节。
5. \*\*提交网关。\*\*账本里的东西都只是“说”；要对外部世界“做”，必须经过提交网关，见《记忆与权限：提议和提交分开》一节。

![图 2：Table 的分层架构。Table Core 只持有协作状态；每个 bot 的推理、记忆和凭证都留在主人那边](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/fig2.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=0d1aa690c269ba585f2f487b307e10a8)

协议里的一条账本条目长这样：

```json theme={null}
{
  "seq": 15,
  "table": "agent-prio-w45",
  "seat": "judge",
  "kind": "decision",
  "body": "Prioritize #459 first because it is confirmed active customer harm: silent row loss produces incomplete business records. Stabilize #461 immediately afterward; …",
  "effects": [{ "owner": "jenny", "resource": "taskboard", "action": "reorder",
               "args": { "order": ["#459 Acme CSV export drops rows", "#461 prefix-cache test flaky on CI", "#462 SDK docs examples"] } }],
  "budget": { "tokens_used": 477 },
  "ts": "2026-11-03T12:04:09.956Z"
}
```

`effects` 写明这条决议会动谁的什么资源，审批按它路由，不靠 bot 自己判断。`budget` 记下这条发言花了多少 token。条目还可以带 `refs`，里面只放 `entry:<seq>` 这样的引用 ID、不放内容，需要时再按引用逐跳展开。

***

## 任意拓扑：拓扑是策略，不是代码

多 agent 系统常见的做法是为每种协作形态写一套编排代码：辩论一套、流水线一套、主管和下属一套。每套单独维护，彼此切换不了。

在 BYOB Table Protocol 里，拓扑就是三件事：

* \*\*可见性：\*\*每个席位能读到账本的哪些条目；
* \*\*发言规则：\*\*当前谁拿着 floor，说完以后 floor 交给谁；
* \*\*终止条件：\*\*达成决议、轮次用完、token 预算耗尽，或条目数到顶。

同一本账本换一组策略，就是一种新拓扑，数据结构不变，席位也不用重新接入。mcode-agent-table 里已经有 broadcast（轮流发言）、debate（正反方加裁判）、pipeline（流水线）、hub\_spoke（主持人点名）、delegation（按汇报关系逐级委派）五种策略，再加上子桌。

![图 3：五种拓扑加动态子桌，都表达成同一本账本上的策略](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/fig3.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=915a22fc24d0dc45df8fd46e8742623d)

一张辩论桌的配置是这样：

```json theme={null}
{
  "id": "agent-prio-w45",
  "topic": "Which issue goes first this week: #459 or #461?",
  "owners": { "tao":   { "public_key": "<base64 SPKI Ed25519>" },
              "jenny": { "public_key": "…", "auto_approve": [{ "resource": "taskboard", "action": "label" }] } },
  "topology":   { "kind": "debate", "pro": "bot-tao", "con": "bot-jenny", "judge": "judge", "rounds": 2 },
  "visibility": { "judge": ["bot-tao.say", "bot-jenny.say"] },
  "floor":      { "max_chars": 1500, "max_bot_depth": 8, "decision_by": ["judge"] },
  "termination": { "any": ["decision", "rounds_exhausted", { "budget_tokens": 60000 }] },
  "watchdog":   { "heartbeat_ms": 600000 }
}
```

> [!NOTE]
>
> 动态子桌是“任意拓扑”能成立的关键。圆桌讨论到一半，发现两个 bot 要对一个接口细节反复确认，没必要让全桌陪着。

这时开一张子桌，带 `parent` 指向父桌，只拉相关席位进去，它有自己的席位、拓扑和账本。子桌关闭时，Table Core 只往父桌追加一条 `subtable_result`，里面只有子桌的决议和引用，其他细节都留在子桌里。子桌可以继续嵌套：主桌是主持人点名，子桌是辩论，辩论的一方内部又可以是逐级委派。

***

## 发言权与终止：防止 bot 互相回复停不下来

把几个 bot 拉进同一个 IM 群，最先遇到的问题是它们停不下来。每个 bot 都倾向于有人说话就回应：A 回 B，B 谢 A，A 再补一句，很快就刷满屏。

靠 prompt 让每个 bot 自觉“不该说就别说”并不可靠，模型的临场判断不稳定。所以 floor 在 Table Core 里是硬约束：

* \*\*没有 floor 的席位写不进发言。\*\*say、pass、proposal、decision 只有 floor 持有者能写，其他席位会收到 `E_NOT_FLOOR`，可以写 `raise_hand`，由策略决定什么时候轮到它。人类席位随时可以说话。
* \*\*每次授予 floor 都带预算。\*\*授予记录里写明字数上限，超了由 Table Core 直接截断并标上 `truncated`，不靠 bot 自己收尾。整张桌还有 token 总预算。
* \*\*bot 对 bot 的回复有深度限制。\*\*人类发言把计数清零；连续 N 条只有 bot 在说话，floor 自动交给桌上的人类，桌上没有人类就直接关桌。
* \*\*终止需要显式条件。\*\*决议、轮次用完、token 预算耗尽、条目数到顶，至少配一条。没有终止条件的桌子开不出来，创建时直接报错。
* \*\*沉默是合法输出。\*\*被点名的席位可以回 `pass`，比勉强凑一句“我同意以上观点”有用。

直接拉一个飞书群难就难在这里。IM 群里没有 floor 这回事，只能靠每个 bot 各自遵守“只回被 @ 的消息”。这样能跑，但规则分散在每个 bot 的 prompt 里，有一个不守规矩，整个群就会失控。

![图 4：一轮发言的完整路径：入账 → 策略求值 → 投影 → 点名 → 异步执行 → 回写 → 收敛 → 批准](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/fig4.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=0f93653525e16409be3d252b7d69b66b)

***

## 每个席位的上下文：投影，而且要缓存友好

桌上的 bot 不读整本账本。一张开了两周的桌子，账本可能有几千条，全部塞进每个 bot 的上下文，既贵又稀释注意力。Table Core 为每个席位生成一份**投影**：

* \*\*稳定前缀：\*\*桌规、席位表与能力卡、已生效的决议。只有新席位入座或出了新决议时才会变，投影里带着前缀的 sha256，bot 一比就知道前缀变没变。前缀放在最前面，留给 prompt cache。
* \*\*增量尾巴：\*\*从该席位上次读到的 seq 之后、且策略允许它看到的条目。只追加，不重排。
* \*\*引用而非内容：\*\*超过长度上限的内容会被截短，附上 `entry:<seq>` 引用，需要时再按引用取全文。

容易踩的坑是在投影里放每轮都变的东西。投影里没有时间戳、在线状态这类字段，条目的 `ts` 也会被去掉，否则前缀每轮都会失效。需要时间，就作为尾巴里的一条事件给出。我们在 MCode 工程笔记 05 里讲“Agent 怎么知道当前时间”时，处理的是同一个问题。

投影由 Table Core 生成，怎么拼进 bot 自己的上下文，是 bot 的事。协议只固定投影的格式和顺序。MCode 接入端的做法是：一个 session 的第一轮发前缀加尾巴，之后只发新增的尾巴。

***

## 记忆与权限：提议和提交分开

### 两种记忆

BYOB 下有两种记忆，必须分开：

* **桌面记忆**归桌子所有：议题、决议、分工、未完成事项。任何新入座的席位都能读到（受可见性约束）。
* **私有记忆**归各自主人：bot 对主人的长期了解。它永远不会被桌子读走。

两者之间只有一个通道，就是 bot 的发言。bot 说出口的内容进入桌面记忆；没说出口的，桌子不知道。所以每个 bot 带一份由主人设定的**披露规则**：哪些话题可以引用私有记忆，哪些只能说结论不能说来源，哪些一律不提。例如“可以说我周四下午有空，不能说为什么没空”。披露规则在席位一侧的客户端里执行，发言离开主人的机器之前就过滤掉，桌子从头到尾碰不到私有记忆。

### 提议与提交

我们一直守着一条原则：agent 只能提议，对外动作由它够不着的系统执行，隔离边界要和权限边界对齐。放到多主人的桌子上，这条规则变成：

> [!NOTE]
>
> 桌上的任何 bot 都只能以自己主人的权限行动。影响别的主人资源的动作，只能写成提议，由那个主人批准，并由那个主人的 bot 执行。

具体说：

1. proposal 的 `effects` 字段列出受影响的主人和资源；
2. Table Core 按 `effects` 开一个任务，状态是等待对应主人审批；如果主人预先设好的自动批准规则覆盖了全部 effects（比如“我自己的任务板，打标签可以自动批准”），就直接放行；
3. 主人的批准是一条用他的 Ed25519 私钥签名的条目；批准后，由该主人自己的 bot 在它自己的执行面落地，回写一条 receipt，再由另一个席位（独立的 bot 或确定性检查）写 verify，执行者不能自己验自己；
4. 桌子本身不持有任何人的凭证，所以即便桌子被 prompt 注入攻破，攻击者拿到的也只是“提议”的能力。

按这条规则，桌上最坏的情况是有人说了错话；对外的动作都要经过对应主人审批。

![图 5：桌上一件事的状态机。等批准、在跑、已回执、已核验都是账本里的显式状态](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/fig5.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=93bafa14554dae8550884d97a89e85df)

### 异步完成信号

异步任务要让人分清“在跑、跑完了、等你批”，单个 agent 都没完全做好，多个 bot 更难，因为 bot A 看不到 bot B 的进程。

我们的做法是以账本状态为准，不以 bot 自述为准。任务在账本上有显式状态机（图 5）：先等受影响的主人批准（`awaiting_approval`），批准后（`approved`）执行的 bot 回 `running`，后台继续跑，完成后写 receipt，状态变成 `reported`。批准后或运行中的任务在心跳时间内没有进展，Watchdog 把它标为 `stalled`。要等另一个席位或一个确定性检查写下 verify pass，任务才到 `verified`，这才算做完，执行者不能核验自己的回执。bot 说“我做完了”，在账本里只是一条 receipt。

***

## 协议层：怎么把不同的 bot 接上桌

不同 bot 的开放程度差别很大。传输层是 HTTP 加 SSE，mcode-agent-table 在上面提供了几种接入方式：

| 接入方式 | 适用 | 做什么 |
| - | - | - |
| HTTP + SSE | 能发 HTTP 请求的 agent，用仓库里的客户端库或 CLI | 直接读写账本，用 SSE 订阅新条目 |
| MCP | 支持 MCP 的 agent。仓库自带一个 MCP server，12 个工具：`byob_join`、`byob_read_projection`、`byob_say`、`byob_propose`、`byob_approve` 等 | agent 把入座、读投影、发言、提议当成普通工具调用 |
| A2A | 支持 agent-to-agent 协议的 bot | 桥接还没做，排在路线图里；目标是把“任务 + 消息 + 产物”的往来映射到账本状态机 |
| CLI / SDK | 可以无界面调用的 agent。MCode 接入端基于 `@minimax-ai/code-sdk` | 接入端读投影、拼 prompt、起 MCode 会话，把输出写回成该席位的发言或回执 |
| 代理席 | 没有开放接口的产品 | 由人转述，或用公开资料扮演其视角，并在席位上明确标注“代理” |

MCP 管 agent 调工具，A2A 管 agent 对 agent。桌子在两者之上补了三样它们没定义的东西：floor（谁能说话）、effects（这条消息会影响谁）、主人签名（这个席位确实代表这个人）。BYOB Table Protocol v0.1 新增的就是这三样，规范和 Schema 都在仓库里，欢迎各家一起改。

今天的 Personal Agent 多数能接入你的邮箱和日历，却接不进别人的 agent。

***

## 会怎么失败

多 bot 协作有几种单 agent 没有的失败方式，设计时就要考虑：

* \*\*群体思维。\*\*后发言的 bot 倾向于附和先发言的。缓解：重要议题先“背靠背”独立出意见（彼此不可见），再公开讨论。这在拓扑上就是先开 N 个单人子桌，再合并。
* \*\*谄媚放大。\*\*每个 bot 都想讨好人类，几个 bot 一起讨好，会迅速收敛到人类最初的倾向。缓解：设一个红队席，策略上要求它必须提出至少一条反对意见。
* **规格博弈。**“删掉 src/，bug 就是 0”。多 bot 下更隐蔽：A 声称完成，B 只看了 A 的总结就签字。缓解：verified 必须由确定性检查或拿到原始产物的独立席位完成。
* \*\*成本失控。\*\*N 个 bot、每轮每人一份投影，成本是 N 倍起步。缓解：floor 预算、桌级总预算、投影缓存命中率作为一等指标监控。
* \*\*披露越界。\*\*bot 为了把事办成，引用了主人不希望公开的信息。缓解：披露规则 + 事后审计 + 敏感话题强制转人工。
* \*\*冒名。\*\*一个席位声称代表某人。缓解：入座需要主人签名，能力卡由主人一侧签发。

评估指标也要变。单 agent 看任务完成率，桌子还要看达成决议用了多少轮、多少 token；人类介入了几次；有多少提议被拒；同一个议题换拓扑以后质量和成本怎么变。这组对比是我们接下来要跑的。

***

## 我们把这张桌子做出来了

前面讲的是一张桌子需要什么：账本、席位、拓扑、发言权、投影、审批。这些都已经写成了代码，就是 [mcode-agent-table](https://github.com/MiniMax-AI/mcode-agent-table)：一个桌子宿主（`byob serve`），里面跑着 Table Core 和一本 JSONL 账本，再加上几种让不同 bot 入座的接入端。bot 留在各自主人的机器上，主人的密钥不出本机。下面是这张桌子第一次坐满的样子。

### 一次真实的会话

议题很普通，每个团队每周都会争一次：这周只够做完一件事，先修 #461 还是 #459？#461 是 prefix cache 回归测试在 CI 上不稳定，卡着 0.7.2 发版；#459 是客户 Acme 的 CSV 导出丢行。

桌上有四个席位。前三个是真实的 MiniMax Code agent（mcode 0.6.5，模型 MiniMax-M3），通过 `@minimax-ai/code-sdk` 接入；第四个是一段不调模型的检查代码。

* **bot-tao**：代表我，正方，主张先修 #461。
* **bot-jenny**：代表 Jenny，反方，主张先修 #459。团队任务板归 Jenny 管。她的 bot 带着两条私有记忆：Acme 在电话里说过，下周一前修好就行；Jenny 周四要去看牙。Jenny 给它的披露规则是：可以说她周四不在，不能说为什么。
* **judge**：裁判，主人是 ops，只看得到正反方的发言。
* **checker**：核对执行结果，不调模型。

双方各说两轮，裁判判 #459 先做，决议的 effects 是重排 Jenny 的任务板。任务板不归裁判，也不归我，所以 Table Core 开了一个任务，等 Jenny 审批。审批入账后，由 Jenny 自己的 bot 动手：它在 Jenny 的工作区里改了 `taskboard.json`，在回执里写明改动，还提了一句“Acme 接受下周一前修好”，这在她的规则允许范围内。checker 读磁盘上的文件，确认顺序和批准的 effects 一致，任务才变成 verified。“看牙”从头到尾没进过账本。

> [!NOTE]
>
> 桌上的 bot 可以争，也可以说错话。但动手改东西的只能是资源主人自己的 bot，而且要另一个席位核过才算数。

从开桌到 verified，账本一共 25 条。节选如下（原文是英文，长发言做了截断）：

```text theme={null}
[#1]  core system/table_opened: This week the team can finish only one of: #459 (Acme CSV export drops rows) or #461 (prefix-cache test flaky on CI; blocks 0.7.2) …
[#2]  core system/seat_joined: bot-tao joined for tao
[#3]  core system/seat_joined: bot-jenny joined for jenny
[#7]  bot-tao say to @judge: Prioritize #461. The flaky prefix-cache regression test can mask genuine cache correctness or performance regressions …
[#9]  bot-jenny say to @judge: #459 should go first. It is already causing active customer harm: Acme's CSV export silently drops rows …
[#15] judge decision: Prioritize #459 first because it is confirmed active customer harm …
      effects: [{"owner":"jenny","resource":"taskboard","action":"reorder", …}]
[#16] core system/task_opened re #15 task-15: task-15 awaiting approval from owner jenny
[#17] core system/table_closed: table closed: decision #15
[#18] owner:jenny approval re #16 task-15   nonce=fa3b98d4…  signature=d/SaImtMCiuE2k59…
[#19] core system/task_state to @bot-jenny task-15: task-15 approved by jenny; executor bot-jenny
[#22] bot-jenny receipt re #16 task-15: I reordered the taskboard … to the requested sequence #459 → #461 → #462 …
[#23] core system/task_state task-15: task-15 reported by bot-jenny; needs verify from another seat
[#24] checker verify re #22 task-15 result=pass: taskboard.order matches the approved effect
[#25] core system/task_state task-15: task-15 verified by checker
```

第 18 条的批准，是运行程序拿 Jenny 的主人密钥签的，代替她本人点击；Table Core 用 Jenny 的公钥验过签名才让它入账。三个 MCode 席位一共调了六次模型，用掉 48,381 个 token。完整账本、可读记录和每轮 token 用量都在[仓库](https://github.com/MiniMax-AI/mcode-agent-table/tree/main/demo/out/mcode)里。

### 五分钟摆一张自己的桌子

需要 Node 22.19 以上：

```bash theme={null}
git clone https://github.com/MiniMax-AI/mcode-agent-table && cd mcode-agent-table
npm install
npm test                 # 61 个测试

# 终端 1：启动桌子宿主
npx tsx src/cli.ts serve --port 7341 --data ./data

# 终端 2：生成主人密钥、开桌、入座
npx tsx src/cli.ts keygen tao --out tao.owner.json      # 这个文件别外传
PK=$(node -p "require('./tao.owner.json').publicKey")
cat > table-config.json <<JSON
{ "id": "my-table", "topic": "hello",
  "owners": { "tao": { "public_key": "$PK" } },
  "topology": { "kind": "broadcast", "order": ["bot-tao"], "rounds": 2 },
  "termination": { "any": ["rounds_exhausted"] } }
JSON
npx tsx src/cli.ts create table-config.json             # 打印桌号和管理员令牌
npx tsx src/cli.ts join my-table --owner tao.owner.json --seat bot-tao --bot my-agent --out tao.seat.json
npx tsx src/cli.ts say  --seat tao.seat.json "hello table"
npx tsx src/cli.ts read --seat tao.seat.json            # 本席位看到的前缀 + 尾部
```

完整的配置格式（可见性、发言权、看门狗、子桌）见 [SPEC.md](https://github.com/MiniMax-AI/mcode-agent-table/blob/main/SPEC.md)。去掉 `termination`，`create` 会直接拒绝这张桌子：走 HTTP 返回 `E_SCHEMA`，Table Core 内部是 `E_NO_TERMINATION`。这是故意的。

### 你的 bot 怎么入座

* \*\*MCode。\*\*接入端 `src/adapters/mcode.ts` 基于 `@minimax-ai/code-sdk`。每个席位只开一个 MCode 会话，第一轮发前缀加尾巴，之后只发新增的尾巴。
* **任何支持 MCP 的 agent（Claude Code、Codex、Cursor……）。**`byob mcp` 是一个跑在主人机器上的 stdio MCP server，12 个工具覆盖入座、读投影、发言、pass、举手、提议、决议、审批、进度、回执、核验和桌面记忆。能力卡从 `BYOB_CARD_FILE` 读，agent 自己改不了；`byob_approve` 会通过 MCP elicitation 请主人确认，客户端不支持确认就直接拒绝，主人也随时可以自己跑 `byob approve`。在客户端的 MCP 配置里这样写：

```json theme={null}
{ "mcpServers": { "byob": {
    "command": "npx", "args": ["tsx", "/path/to/mcode-agent-table/src/cli.ts", "mcp"],
    "env": { "BYOB_URL": "http://127.0.0.1:7341", "BYOB_TABLE": "my-table",
             "BYOB_OWNER_KEY_FILE": "/path/to/tao.owner.json",
             "BYOB_CARD_FILE": "/path/to/tao.card.json" } } } }
```

* **自己写代码接入。**`src/client.ts` 里的客户端库管密钥、签名、席位循环和披露检查：`SeatClient.join()` 入座，`runSeat()` 在轮到你时调用你的 agent。也可以直接用 `byob` 命令行，`say`、`pass`、`propose`、`approve`、`read` 都有。

不管哪种方式，入座都要带主人的 Ed25519 签名和一次性 nonce。所以你的 bot 一坐下，桌上每个席位都知道它代表谁、能动什么，别人也冒充不了它。

***

## 路线图

![图 6：v0.1 已开源，接下来两步](https://mintcdn.com/agent-cn/o5-Kp97QONhj3_HL/images/techblog/byob-agent-table/fig6.png?fit=max\&auto=format\&n=o5-Kp97QONhj3_HL\&q=85\&s=38ea5d5fffe718a99c93c24f3e783fa1)

v0.1 就是上面这套，只有一个桌子宿主，已经开源。接下来两步：

* \*\*更多真人、真 bot。\*\*让 Grok Bot 等更多 bot 通过 MCP 入座；签名从入座和批准扩到每条发言；一条提议涉及几个主人，就让他们分别批准；终止条件里加上投票和法定人数。提示缓存也要补上：投影保住了稳定前缀，MCode 接入端每个席位复用一个会话，但命中率还没测过，也没调过（上面那次运行每轮只读到 128 个缓存 token）。
* \*\*开放协议。\*\*桌子宿主之间做联邦，让别的机器、别的组织的席位也能入座；WebSocket 传输和 A2A 桥映射到同一组接口上；规范的修订流程公开。验收只看一件事：有一个不是 MiniMax 的 bot，照着规范自己接了进来。

***

## 几个值得讨论的问题

下面这些问题我们有倾向，但还没定。

* \*\*桌主该是谁？\*\*主持人如果是某个参与者的 bot，就有利益冲突；如果是中立的 bot，它又归谁管？我们倾向于桌主也必须有主人，并且写在席位上。
* \*\*每句话都要签名吗？\*\*v0.1 里主人只签入座和审批，普通发言靠席位 token 认证。每句都签更安全，也更重。这条线该画在哪？
* \*\*一条提议同时动三个人的资源，怎么批？\*\*v0.1 一条提议只影响一个主人。全员同意、多数同意，还是按资源逐个批？
* \*\*披露规则谁来写？\*\*普通用户不会写策略。我们的想法是让 bot 先问主人，再慢慢沉淀成规则。有更好的办法吗？
* \*\*协议由谁来定？\*\*如果每家只支持自己的桌子，BYOB 就成了又一个封闭生态。我们会把规范的修订流程公开出来。

## 结语

在互相信任的团队里，每个人都已经有自己的 bot。下一步是别再让人在 bot 之间传话，让这些 bot 直接坐下来一起推项目，同时谁都不用交出自己的记忆和凭证。

桌子已经摆好了：[MiniMax-AI/mcode-agent-table](https://github.com/MiniMax-AI/mcode-agent-table)。带上你的 bot 来入座。
