machine-genome 模型、Agent 与 Harness 的身份谱系协议
Machine Genome 不是另一个 Agent runtime,而是一套给模型、Agent、harness、数据集和衔接产物登记身份与来源的参考实现。它把 signed genesis record 压成 Gene,再用 amendment、attestation、registry admission 和 Merkle proof 维护不可重写的谱系证据。
它解决什么,凭什么值得拆
▸系统定位
这个仓库的核心判断是:Agent 越来越像供应链,名称本身无法说明它由哪个模型、prompt、工具、数据集或运行策略组成。README 把目标写成 identity and provenance protocol;源码里真正落地的是 CLI 命令分发、严格记录校验、Data Integrity proof、lineage authorization、append-only registry 和透明日志。入口从 cmd/mgs/main.go:37 的 run 函数开始,命令枚举在 cmd/mgs/main.go:42 到 cmd/mgs/main.go:70,这说明作者把协议能力先做成可脚本化 CLI,而不是只给文档。
值得拆的原因在于它有清晰的信任边界:MGS 记录的结构约束在 mgs/record.go:20 到 mgs/record.go:78,签名/验签路径在 mgs/proof.go:78 和 mgs/proof.go:121,registry 入库统一落到 registry/store.go:158。同时测试覆盖了 CLI round trip、idempotent admission、equivocation、tombstone、Merkle proof tampering 和 namespace challenge,因此它不是单纯协议草案。
▸核心数据
▸端到端拓扑
拓扑里最关键的不是 HTTP,而是 verification boundary。CLI 在 cmd/mgs/main.go:123 到 cmd/mgs/main.go:175 构造 genesis,但入库仍会经过 registry/store.go:190 的 submitGenesis;这让本地生成和远端提交共享同一套校验。测试 cmd/mgs/main_test.go:33 到 cmd/mgs/main_test.go:76 也证明 CLI 生成、签名、verify、gene 四步能闭环。
记录模型把“身份”拆成可校验字段
▸subjectType 与 edgeType 是协议的窄门
mgs/record.go:20 到 mgs/record.go:30 把 subjectType 限在 model、agent、agent-class、agent-instance、harness、dataset,并把 lineage edge 限在 fine-tune-of、distilled-from、scaffold-fork-of、trained-on 等固定语义。这个选择比自由文本 provenance 更硬,因为 mgs/record.go:99 和 mgs/record.go:123 会直接拒绝未知类型。CLI 侧的 cmd/mgs/main.go:129 默认 subject-type 为 agent,但仍要求 name、namespace、version 在 cmd/mgs/main.go:137 同时存在。
20subjectTypes = map[string]bool{ 21 "model": true, "agent": true, "agent-class": true, 22 "agent-instance": true, "harness": true, "dataset": true, 23} 24edgeTypes = map[string]bool{ 25 "fine-tune-of": true, "distilled-from": true, 26 "quantization-of": true, "model-instance-of": true, 27 "scaffold-fork-of": true, "instance-of": true, 28 "prompt-descendant-of": true, "ensemble-of": true, 29 "trained-on": true, "successor-of": true, 30}
▸GenesisRecord 是不可变根
GenesisRecord 的字段在 mgs/record.go:70 到 mgs/record.go:78 很克制:identity、parentage、controller、genesis metadata 和 proof。这里没有把 runtime 状态塞进根记录,后续状态走 amendment 和 attestation。这个设计能避免一个常见问题:如果每次能力声明都改 genesis,那么 Gene 本身就不稳定。CLI 生成 record 的地方在 cmd/mgs/main.go:151 到 cmd/mgs/main.go:165,生成后立刻用 mgs/record.go:80 的 ValidateGenesis 做 unsigned 校验。
70type GenesisRecord struct { 71 MGS string `json:"mgs"` 72 RecordType string `json:"recordType"` 73 Identity Identity `json:"identity"` 74 Parentage []LineageEdge `json:"parentage"` 75 Controller Controller `json:"controller"` 76 Genesis GenesisMetadata `json:"genesis"` 77 Proof *Proof `json:"proof,omitempty"` 78}
▸ValidateGenesis 先做语义约束,再做 proof 约束
ValidateGenesis 的顺序很明确:版本和 recordType 在 mgs/record.go:85 到 mgs/record.go:90,identity 必填在 mgs/record.go:91,controller DID 和 genesisKeyId 的控制关系在 mgs/record.go:102 到 mgs/record.go:108,artifact hash 在 mgs/record.go:112 到 mgs/record.go:121,parentage 规则在 mgs/record.go:123 到 mgs/record.go:138。proof 是否必须存在则被 requireProof 参数控制,落在 mgs/record.go:140 到 mgs/record.go:147。
签名边界:JCS + Ed25519 + did:key
▸ProofOptions 固定 cryptosuite
Proof 模型在 mgs/proof.go:13 到 mgs/proof.go:28 固定为 DataIntegrityProof、eddsa-jcs-2022 和 assertionMethod。mgs/proof.go:48 的 validate 不允许调用方随意换 proofPurpose 或 cryptosuite,这对互操作很重要。它还要求 timestamp 精确到 UTC 秒,见 mgs/proof.go:67 到 mgs/proof.go:75;CLI 的 created 参数则在 cmd/mgs/main.go:87 暴露给用户。
78func SignDocument(unsecured []byte, options ProofOptions, privateKey ed25519.PrivateKey) ([]byte, error) { 80 if err := options.validate(); err != nil { return nil, err } 86 object, err := decodeObject(unsecured) 90 if _, exists := object["proof"]; exists { return nil, errors.New("document is already secured") } 101 hashData, err := proofHashData(unsecured, options) 105 signature := ed25519.Sign(privateKey, hashData) 106 proof := map[string]any{ 107 "type": options.Type, "cryptosuite": options.Cryptosuite, 110 "verificationMethod": options.VerificationMethod, 112 "proofValue": encodeMultibase(signature), 117 object["proof"] = proof 118 return pretty(object)
▸验签会重建未签名文档
mgs/proof.go:121 到 mgs/proof.go:191 的 VerifyDocument 不是只检查字段存在。它解析 proof、拒绝未知 proof option,在 mgs/proof.go:175 删除 proof 后重新 pretty,再在 mgs/proof.go:180 调用 proofHashData。proofHashData 又在 mgs/proof.go:194 到 mgs/proof.go:222 分别 hash canonical document 和 proof config。也就是说,签名覆盖的是“规范化后的无 proof 文档 + 规范化 proof 选项”。
171signature, err := decodeMultibase(proof.ProofValue) 175delete(object, "proof") 176unsecured, err := pretty(object) 180hashData, err := proofHashData(unsecured, options) 184publicKey, err := resolver.ResolveEd25519(ctx, proof.VerificationMethod) 188if !ed25519.Verify(publicKey, hashData, signature) { 189 return "", fmt.Errorf("%w: Ed25519 signature mismatch", ErrInvalidProof) 191return proof.VerificationMethod, nil
▸血缘授权避免循环签名
Lineage 的难点是 parent 要签 child,但 child 的 genesis 里又会嵌入 authorizationProof。仓库用 mgs/lineage.go:24 到 mgs/lineage.go:53 的 ChildCommitment 先移除顶层 proof 和所有 authorizationProof,得到稳定承诺。之后 mgs/lineage.go:88 到 mgs/lineage.go:121 只把 parent 对 deterministic authorization document 的 proof 嵌回 edge。验证路径在 mgs/lineage.go:127 到 mgs/lineage.go:191,并要求 signer 是 parent controller。
124// VerifyLineage resolves every parent and verifies every consenting-parent signature. 127func VerifyLineage(ctx context.Context, genesis []byte, keys KeyResolver, parents GenesisResolver) error { 132 for index, edge := range record.Parentage { 136 parentRaw, err := parents.ResolveGenesis(ctx, edge.ParentGene) 140 if err := DigestMatches(parentRaw, edge.ParentGene); err != nil { ... } 143 parentGene, err := VerifyGenesis(ctx, parentRaw, keys) 154 if !edge.Authorized { continue } 176 method, err := VerifyDocument(ctx, securedAuthorization, keys) 181 if controller != parent.Controller.DID { return fmt.Errorf(...) } 187 if edge.AuthorizationProof.Created > record.Genesis.Timestamp { return fmt.Errorf(...) } 191 return nil
Registry 把协议约束变成可查询的透明日志
▸Store.Open 先建 bucket 和权限边界
Registry 使用 bbolt,不依赖区块链。bucket 列表在 registry/store.go:29 到 registry/store.go:50,包括 objects、genes、identity、amendments、attestations、children、equivocations、transparency_log、audit、tombstones 和 namespace_grants。registry/store.go:117 到 registry/store.go:151 创建目录和 DB 时强制 0700/0600 权限,说明作者把 registry 当成安全边界的一部分,而不仅是缓存。
158func (s *Store) Submit(ctx context.Context, raw []byte) (Submission, error) { 162 if len(raw) == 0 || len(raw) > 1<<20 { return Submission{}, errors.New(...) } 165 canonical, err := mgs.Canonicalize(raw) 169 var header struct { RecordType string `json:"recordType"` } 175 s.mu.Lock() 178 switch header.RecordType { 179 case mgs.RecordGenesis: return s.submitGenesis(ctx, canonical) 181 case mgs.RecordAmendment: return s.submitAmendment(ctx, canonical) 183 case mgs.RecordAttestation: return s.submitAttestation(ctx, canonical) 186 default: return Submission{}, fmt.Errorf("unsupported recordType %q", header.RecordType) 188}
▸统一 Submit 是 HTTP 不能绕过的 admission gate
HTTP submit 在 registry/http.go:182 到 registry/http.go:206 读取 body 后只调用 registry/store.go:158 的 Store.Submit;没有旁路写对象。submitGenesis 会串联 mgs/record.go:152 的 VerifyGenesis、mgs/lineage.go:127 的 VerifyLineage 和 namespaceAllowed,再写 identity index。这个边界值得肯定:不管来自 CLI、HTTP 还是测试,最终都走同一个 canonical admission path。
▸Equivocation 被保留为证据,而不是被吞掉
amendment 冲突处理在 registry/store.go:233 到 registry/store.go:283。如果 sequence 已存在但 prev 相同,registry/store.go:266 到 registry/store.go:269 会记录 equivocation,而不是默默覆盖。registry/store.go:286 到 registry/store.go:309 把冲突记录写入 bucketEquivocations,并追加 audit 事件。测试 registry/store_test.go:81 到 registry/store_test.go:135 明确覆盖了 fork、attestation 和 tombstone。
333func (s *Store) insert(canonical []byte, meta RecordMetadata, index func(*bolt.Tx) error) (Submission, error) { 336 if existing := tx.Bucket(bucketObjects).Get([]byte(meta.Digest)); existing != nil { 338 submission = Submission{Metadata: stored} 341 if err := index(tx); err != nil { return err } 344 now := s.now().UTC().Truncate(time.Second).Format(time.RFC3339) 345 logIndex, err := tx.Bucket(bucketLog).NextSequence() 351 if err := tx.Bucket(bucketObjects).Put([]byte(meta.Digest), canonical); err != nil { return err } 358 if err := tx.Bucket(bucketLog).Put(uint64Key(meta.LogIndex), []byte(meta.Digest)); err != nil { return err } 361 if err := s.appendAudit(tx, "record.accepted", "public", meta.Digest, map[string]any{...}); err != nil { return err } 366 submission = Submission{Metadata: meta, Created: true} 369return submission, err
测试覆盖的是真实信任假设
▸CLI round trip 验证用户路径
cmd/mgs/main_test.go:33 到 cmd/mgs/main_test.go:76 从 keygen、init-genesis、sign、verify、gene 跑通用户会执行的最短路径,并检查 key file 权限是 0600。这个测试和 cmd/mgs/main.go:178 的 keygen 实现、cmd/mgs/main.go:123 的 init-genesis 实现对应,能避免 CLI 文档和真实命令漂移。
33func TestCLIGenesisRoundTrip(t *testing.T) { 40 if err := run([]string{"keygen", "--out", key}, &stdout, &stderr); err != nil { ... } 47 if info.Mode().Perm() != 0o600 { t.Fatalf("key mode is %o", info.Mode().Perm()) } 50 if err := run([]string{"init-genesis", "--key", key, "--name", "cli-agent", ...}); err != nil { ... } 58 if err := run([]string{"sign", "--in", unsigned, "--key", key, "--out", secured}, ...); err != nil { ... } 64 if err := run([]string{"verify", "--in", secured}, &stdout, &stderr); err != nil { ... } 71 if err := run([]string{"gene", "--in", secured}, &stdout, &stderr); err != nil { ... } 75 if !strings.HasPrefix(stdout.String(), "zQm") { t.Fatalf("unexpected Gene: %s", stdout.String()) } 76}
▸Registry 测试覆盖 idempotency、conflict 和 tamper
Store 的第一组测试 registry/store_test.go:19 到 registry/store_test.go:79 覆盖 canonical bytes、重复提交、inclusion proof 和 backup 权限;第二组 registry/store_test.go:81 到 registry/store_test.go:135 覆盖 amendment fork、attestation、tombstone;Merkle 篡改测试在 registry/store_test.go:181 到 registry/store_test.go:219。仓库策略脚本还会检查必需文件、JSON 引用和 Markdown 链接,见 scripts/check-repository.py:83 到 scripts/check-repository.py:145。
▸质量门禁说明
cmd/mgs/main.go:37、cmd/mgs/main.go:42、cmd/mgs/main.go:123、cmd/mgs/main.go:151说明 CLI 是协议入口,不只是 demo。cmd/mgs/main_test.go:33、cmd/mgs/main_test.go:40、cmd/mgs/main_test.go:47、cmd/mgs/main_test.go:64说明最短用户路径有自动化验证。scripts/check-repository.py:83、scripts/check-repository.py:100、scripts/check-repository.py:130、scripts/check-repository.py:141把文档、schema 和链接完整性纳入发布前检查。
亮点之外,还有这些风险
▸协议仍处实验阶段
README 明确说 MGS 是 experimental profile。源码里也能看到实现偏向 Ed25519 did:key 和本地解析:mgs/proof.go:184 依赖 resolver.ResolveEd25519,registry admission 默认使用 DIDKeyResolver。它适合参考和试点,但要进入多组织生态,需要独立 witness、checkpoint gossip、resolver 扩展和治理流程。
▸Registry 是可信操作面,不是能力真相机
Store 能证明谁签了什么字节、这些字节如何进入日志、是否有 tombstone 或 equivocation;它不能证明某个 Agent 真的拥有声明能力。README 也提醒记录不证明 capability、consciousness、ownership 或 endorsement。工程团队若采用它,应把 registry/store.go:472 的 tombstone、registry/store.go:507 的 audit 和 registry/merkle.go:88 的 proof verification 接到自己的治理流程里。