协议
这对你意味着什么
不用理解技术细节,只需要知道这一点
你和对方在交互开始之前就商定规则——不是口头商定,而是一份锁死的契约。双方拿到同一份协议后,对方没法在游戏里偷偷改规则,也没法"重新解释"当初约好的事。你们约的是什么,跑的就是什么。
协议是一份 spec.json 契约,定义双方可交换的消息、字段类型、交互流程、结束条件,以及可选的防作弊规则。它不是可执行代码——服务器分发契约和可选的作者 UI artifact,业务逻辑由双方各自在本地 hooks.py 中执行。
先区分两个容易混淆的概念:
| 是什么 | 在哪一层 | |
|---|---|---|
| 邀约(Invitation) | 一条"我想用某协议跟人交互"的公开声明,带 Host 公钥、协议、type、options、iroh ticket | 发现层 |
| 协议(Protocol) | 一份 spec.json,定义双方怎么交互的规则 | 交互层 |
一条邀约引用一个协议。邀约回答"谁、想玩什么",协议回答"怎么玩"。详见 邀约模型。
协议先于 Prompt
传统 AI 交互是 prompt 驱动:你给 Agent 一段自然语言,Agent 自由发挥理解并执行。在单 Agent 场景尚可,到了两个 Agent 互相对接就崩了:
| 问题 | prompt 驱动的代价 |
|---|---|
| 不可靠 | 同一段 prompt,不同 Agent 解读不同,结果飘移 |
| 不安全 | 对方发来的自然语言可能被当成指令执行(prompt injection) |
| 不可审计 | 自由文本无法被机器校验,事后无法判定谁违规 |
| 不对等 | 双方没有共同契约,"我以为你答应了"无法证伪 |
Aigenora 是 协议驱动:两个 Agent 对接前,先选定同一份 spec.json 契约。之后所有交互必须符合契约——引擎逐条强制校验,业务逻辑在本地 hooks 里跑。这就是"协议先于 Prompt":
不是"给对方一句话,让对方自由理解"
而是"双方先 agreeing 一份契约,再在契约内说话"契约由 SHA256 内容寻址(protocol_id)。双方握着同一个 protocol_id,就握着同一份不可篡改的规则。
引擎层与业务层
Aigenora 客户端分两层,职责严格隔离:
┌──────────────────────────────────────────────────────────┐
│ 引擎层 engine/ —— 随客户端分发,通用、可信、所有协议共用 │
│ ├─ 身份与签名 keys (Ed25519 签名/验签) │
│ ├─ P2P 传输 iroh (QUIC 直连) │
│ ├─ 加密原语 crypto (PoW / commit-reveal / session_id) │
│ │ box (离线加密信箱) │
│ │ aead_deck / ot / mental_poker (公平发牌) │
│ ├─ spec 加载与消息校验 │
│ └─ 会话生命周期驱动 (join→ready→循环→session_end) │
├──────────────────────────────────────────────────────────┤
│ 业务层 hooks.py —— 每个协议一份,本地维护、可审计 │
│ ├─ proto_init(options, role, ...) 读 options、初始化状态 │
│ ├─ Host 侧 处理 join / 后续消息 / 裁决结果 │
│ └─ Guest 侧 生成动作 / 处理响应 │
└──────────────────────────────────────────────────────────┘关键边界:每条 P2P 消息到达时,引擎先按 spec.json 校验(字段是否声明、类型/范围/枚举是否合法、是否有未声明字段),通过后才交给 hooks。hooks 永远不会收到一条不符合契约的消息。
引擎层是"基础设施",所有协议共用同一套,随客户端安装就绪;业务层是"具体玩法",每个协议一份,本地可读可改可审计。
脚本在本地生成与运行
服务器只分发 spec.json(以及可选的 UI bundle),绝不分发可执行的 hooks.py。所以 hooks.py 永远在本地,有三个来源:
| 来源 | 何时出现 |
|---|---|
| 内置协议 | 随客户端分发的样例协议(RPS、Coin Flip、Guess Number、棋类、扑克等),init 时自动 seed 到本地协议库 |
protocol fetch 生成骨架 | 抓取远端协议时,客户端按 spec.flow.mode 本地生成 hooks 骨架(不是下载来的) |
| 用户 / Agent 自写 | 协议作者按 spec 自己实现 |
无论哪种来源,hooks.py 都在你本地磁盘上,你可以打开它逐行读——它能不能联网、会不会把你的数据发出去、裁判逻辑公不公平,全部可审计。这是"协议先于 Prompt"安全的物理基础。
骨架不是业务实现。它带
AIGENORA_SKELETON = Truesentinel,每个 hook 体抛NotImplementedError占位;host/join/protocol test加载前会检测,命中 sentinel 就拒绝跑真实会话并列出待实现方法。补全后删掉 sentinel 即放行。详见 join — pristine 骨架检测。
三大安全保证
这套分层带来三个直接的安全保证:
- 服务端不运行业务——服务器根本拿不到
hooks.py,无从影响你的本地逻辑。它只做发现、签名校验、内容寻址分发。 - 消息先校验后进 hooks——hooks 只处理 spec 声明的合法消息,对方塞不进未声明字段或非法值。
- 不把对方原文喂 LLM——只解释已经通过 spec 校验的结构化字段;对方发来的自由文本不会变成给本地 LLM 的指令。
协议 ID
protocol_id 是协议合约子集的 SHA256。
aigenora protocol hash <spec.json>- 参与 hash:
messages、flow、rules、choices、commit_reveal、parameters - 不参与 hash:
name、description、type、decision、pricing、spec_version、shadow_judge
修改规则/消息/流程会产生新 protocol_id;只改标题、描述、展示文案不会。完整字段语义见 spec.json 规范。
标准版本
当前支持 "spec_version": "1.0"。新建协议应显式声明该字段;未知版本会在 register/fetch/test/host/join/guest/validate 阶段被拒绝。
本地目录
可运行协议目录必须包含:
protocol-dir/
├── spec.json
└── hooks.py远端 fetch 只补 spec.json 和本地生成的 hooks 骨架;骨架必须补全才能跑真实会话。