多数多智能体框架把所有 Agent 塞进同一个平台:一个模型、一份上下文、一套凭据。BYOB Table Protocol 反过来做——每个人把自己的 bot 留在自己机器上,带着自己的模型、记忆与权限,只是到同一张「桌子」上开会。它是 MiniMax Code 团队开源的 TypeScript 参考实现(协议 v0.1)。本教程按官方 README 六步落地:先离线跑通完整协作链,再自己起桌子、签席位、接 MCP,最后走一遍跨主体的审批闭环。
先弄清:一张桌子上摆了什么
官方 README 把系统拆成四件事,理解这四件,后面每条命令的用途就清楚了:
| 部件 | 作用 | 关键约束 |
|---|---|---|
| append-only JSONL ledger | 记录发言、席位、决策、任务与预算,重放即可重建状态 | 只有 Table Core 能写,seq 从 1 连续递增不留空洞 |
| owner-signed seat | 每个 bot 以某个所有者的身份入席 | 入席用所有者 Ed25519 私钥对 table id / seat / card / nonce 签名,bot 不能替别人签,也不能自行放大 capability card |
| floor control | 同一时刻只有持席者能发言 | 非持席者发言报 E_NOT_FLOOR;pass 也是合法回合;超预算发言被截短;bot 互递深度到顶会把发言权交还给人 |
| task gateway | 把「说做完了」变成可核验的状态 | bot 提议 → 受影响的所有者批准 → 该所有者自己的 bot 执行 → 另一个席位复核,才算完成 |
协议还在 v0.1,边界要提前知道:README 的 Roadmap 明确写了当前只在单个 table host 上跑,跨主机联邦、每条发言都签名、多所有者联合提议、投票与法定人数结束条件、WebSocket 与 A2A 桥、prompt-cache 命中率测量都还没落地;今天的发言靠 seat token 认证,签名目前覆盖入席与批准。别把它当成已经可跨公司部署的生产协议。
Step 1:离线跑通一条完整协作链
git clone https://github.com/MiniMax-AI/mcode-agent-table
cd mcode-agent-table
npm install
npm test # vitest:core / topologies / tasks / HTTP+SSE / persistence / MCP bridge
# 离线演示:辩论 -> 决策 -> 所有者批准 -> 执行 -> 复核
npm run demo:scripted
按 README 的描述,这条脚本化演示不需要外部模型:它用 scripted / echo / 确定性 checker 这几种 seat 把协议链路走一遍。npm test 覆盖账本重放、拓扑、任务网关、HTTP+SSE 与 MCP bridge,先跑一遍能顺便确认本机 Node 版本与依赖没问题。
npm install,否则后面的 tsx 与 SDK 可能起不来。Step 2:起一张自己的桌子
# 终端 1:host 持有 Table Core,通过 /v0.1 提供 HTTP + SSE
npx tsx src/cli.ts serve --port 7341 --data ./data
# 另开终端确认 CLI 用法(README 建议看一眼)
npx tsx src/cli.ts
Step 3:签一把所有者钥匙,建带结束条件的桌子
下面这组命令来自 README 的 Quick start,按原样执行即可拿到 table id 与 admin token:
# 终端 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
# 创建桌子,输出 table id 与 admin token
npx tsx src/cli.ts create table-config.json
termination 是硬性字段:README 明确「A table without one is refused at creation」——缺了结束条件,HTTP 侧报 E_SCHEMA,Table Core 侧报 E_NO_TERMINATION。这不是可以省略的默认项,设计上就是不让一场会无限开下去。另外 tao.owner.json 是 Ed25519 私钥,README 注释写着 keep this file private;别提交、别共享、别塞进 MCP 配置里当公钥用。
SPEC.md 第 3 节;拓扑可选 broadcast / debate / pipeline / hub_spoke / delegation 以及子桌,它们共用同一份账本。Step 4:入席、发言、读自己的视图
# 以 tao 的身份入席,签名后生成席位文件
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
join 这一步会用到所有者的 Ed25519 签名;bot 无法替别人签名,也无法自己放宽 capability card。read 返回的是这个席位自己的投影:一段稳定的哈希前缀(规则、席位、决策,只在入席或落决策时变化)加一段只追加的 tail,且不带时间戳——这样 Agent 的 prompt cache 能一直命中,新消息只从 tail 追加。
别把「说 done」当成做完。README 原话:A bot saying "done" is only speech. Only the ledger state verified means done. 另外拒绝规则跑在 seat SDK 侧(Disclosure on the owner's side),被挡下的发言根本不会上桌;floor 之外的发言会拿到 E_NOT_FLOOR。调试时先看 read 的账本状态,别只看终端回显。
byob say | pass | propose | approve | read(用 npx tsx src/cli.ts 查看用法)。想让自己的代码接管,用 Owner / SeatClient / runSeat 这组 client library,它负责密钥、签名、席位循环与披露拦截。Step 5:把 12 个 MCP 工具接进 Claude Code / Codex / Cursor
README 给的 byob mcp 是跑在所有者机器上的 stdio MCP server。把下面这段加到你客户端的 MCP 配置里(路径按本机实际位置替换):
{ "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" } } } }
12 个工具:byob_join / byob_read_projection / byob_say / byob_pass /
byob_raise_hand / byob_propose / byob_decide / byob_approve /
byob_status / byob_receipt / byob_verify / byob_memory
两条权限红线:① capability card 来自 BYOB_CARD_FILE,绝不由 Agent 自己提供——否则 bot 就能给自己加权限;② byob_approve 会通过 MCP elicitation 向所有者本人求确认,客户端若不支持 elicitation,它会直接拒绝,此时所有者可以退回到命令行执行 byob approve。同时 BYOB_OWNER_KEY_FILE 指向私钥,配置文件本身也别提交到公开仓库。
byob_status 看桌子状态,再用 byob_read_projection 拿到它自己的前缀 + tail。能读出来,说明 host、密钥与 card 三处都配对了。Step 6:走完「提议 → 批准 → 执行 → 复核」
协议的原则是:bots propose; the affected owner approves; that owner's own bot executes; another seat verifies.即 bot 只能提议,受影响的所有者签名批准,由该所有者自己的 bot 去执行,再换一个席位复核,任务才算数;watchdog 会把长时间没动静的任务标成 stalled。
# 命令行侧可用的收口动作(以 README 列出的 byob 子命令为准)
byob propose # 提出一个跨所有者动作
byob approve # 受影响的所有者签名批准(MCP 侧为 byob_approve)
byob receipt # 执行方回贴执行凭据(MCP 侧为 byob_receipt)
byob verify # 另一个席位复核(MCP 侧为 byob_verify)
byob status # 查看任务与账本状态
# 想看真实模型参与的三 Agent 会话(需要 mcode 0.6.3+ 与 MiniMax key)
MINIMAX_BENCH_KEY=... npm run demo:mcode
# 可选:MINIMAX_BASE_URL、BYOB_DEMO_MODEL
README 描述的 demo:mcode 场景很具体:三个不同所有者的 MCode Agent 同坐一张 debate 桌——bot-tao 正方、bot-jenny 反方(持有团队任务板与私有记忆)、judge 只看双方发言,另有一个确定性 checker 坐第四席。judge 的裁决动到了 Jenny 的任务板,所以要等 Jenny 签名批准、由 Jenny 自己的 MCode 改文件并回贴 receipt,最后由 checker 复核。录制好的账本、逐轮 token 用量都在 demo/out/。
真实会话会产生模型调用与费用:demo:mcode 要求 PATH 上有 mcode 0.6.3 或更高,并需要 MINIMAX_BENCH_KEY。凭据只放环境变量、不要写进仓库或日志;先跑通 Step 1 的离线链路再决定要不要花这笔调用。本文主线到此为止,无需任何密钥即可复现。
SPEC.md 是 byob/0.1 的规范性文本,schemas/ 里是 Table Core 运行时校验用的 JSON Schema,覆盖 HTTP+SSE 端点、桌子配置、入席握手、账本条目、投影、拓扑、floor、termination、任务网关、MCP bridge 与全部错误码。常见问题速查
| 现象 | 排查方向 |
|---|---|
| create 报 E_SCHEMA / E_NO_TERMINATION | table-config.json 缺 termination,补上 { "any": ["rounds_exhausted"] } 之类的结束条件 |
| 发言报 E_NOT_FLOOR | 当前不持发言权;等轮到自己,或用 pass 让出回合 |
| bot 说 done 但任务没完成 | 只有账本状态 verified 才算完成,检查 propose/approve/receipt/verify 是否走齐 |
| byob_approve 被拒 | 客户端不支持 MCP elicitation,改用命令行 byob approve 由所有者签名 |
| 入席签名失败 | 核对 tao.owner.json 与配置里 public_key 是否配对、seat 名与 topology order 是否一致 |
| 任务长时间无进展 | 查 byob status,watchdog 会把它标成 stalled,让所有者介入 |
做到哪一步算成功
跑完 npm run demo:scripted 应能看到辩论形成决策、所有者批准、执行方回贴凭据、另一席位复核这一整条链;自己起 host 后,read 能返回带稳定前缀与只追加 tail 的投影,byob_status 在 MCP 客户端里能读到桌子状态;把 termination 从配置里删掉再 create,应当被明确拒绝——这条「反例」能证明你确实理解了协议约束,而不是碰巧跑通。主许可证 MIT。