关于 Two-Key
Two-Key 是面向 AI Agent 工具调用的授权代理,在执行操作前同时检查确定性策略和独立 AI 评审。它可置于 MCP 客户端与现有 MCP 服务之间,并记录加密审计账本。
主要功能
- 01双路径授权与一次性令牌
- 02按签名规则检查调用参数
- 03AI 评审调用并支持多评审者
- 04加密、哈希链式审计账本
- 05支持 SIEM 导出决策记录
适用场景
- 01在 MCP 服务前拦截并授权工具调用
- 02按金额、对象等字段限制操作
- 03将授权决策导出到 SIEM
- 04审计获准与拒绝的调用
MCP 相关
Two-Key 的 MCP 代理位于 MCP 客户端与上游 MCP 服务之间,只展示已签名的工具,并在每次调用前执行双路径授权。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Two-Key
AI Agent 必须同时通过两把独立的密钥授权才能行动。无需人工参与。
面向 AI Agent 的授权与 MCP 网关,采用双路径授权机制。将确定性字节码策略与 AI 评审批准、一次性能力令牌和加密账本相结合。
🎯 问题所在
AI Agent 可以获准使用某个工具,却不一定有权执行该工具所能执行的每一项重要操作。
传统的工具权限回答的是:
“这个 Agent 能调用此工具吗?”
Two-Key 提出的是另一个问题:
“这项具体操作是否获准执行?”
Two-Key 是面向使用工具的 AI Agent 的授权层。在执行重要的工具调用之前,Two-Key 要求通过两个相互独立的路径进行授权:确定性策略路径和独立评审路径:
- 策略密钥(路径 A)。 你签署的规则会编译为字节码。一个小型确定性 VM 会根据从调用自身参数中读取的字段检查每次调用:工具、金额、交易对手、数据类别,以及你定义的字段。它不读取任何自然语言,因此提示词无法诱使它违反规则。
- 评审密钥(路径 B)。 一个或多个 AI 评审器各自使用独立凭证,根据你编写的章程审核调用。如果评审器持有 Agent 自身的凭证,Two-Key 就会拒绝启动。
只有两把密钥都通过后,Two-Key 才会签发一次性令牌,该令牌绑定到确切参数、已签名的章程和账本状态。网关只有凭此令牌才会运行工具;每项决策,无论批准还是拒绝,都会写入带签名头部的加密哈希链账本。
你将获得:
- 适配你现有的 Agent。 Grok、ChatGPT、Claude、Gemini 或本地模型(即 Ollama)会以数据形式提出调用;由 Two-Key 作出决定。
- 由你选择评审器。 xAI、OpenAI、Anthropic、Gemini 或本地模型。起步时一个评审器就够;
high_assurance配置会要求评审器来自两个厂商,且本地评审器也给出肯定答复。 - 可置于任何 MCP 服务前(0.5.0)。
two-key mcp-proxy只向 Agent 展示你已签名的工具,并通过两把密钥处理每次调用。 - 事实来自你的系统,而非 Agent(0.5.0)。例如,“此发票与其采购订单相符”这样的字段来自你自己的查询,并会在工具运行前再次查询。
- 可核查的审计轨迹。 静态数据采用 AES-256-GCM 加密,使用哈希链,并由主体密钥和见证密钥签署链头;还提供
two-key audit。 - 将副本发送到你的 SIEM(0.7.0)。每项决策写入时都可发送到 syslog 或 HTTPS webhook,格式可选 Two-Key 自有模式、ECS 或 OCSF,包含原因代码和摘要,但不包含参数值。即使采集器宕机,也不会阻止决策。
- 密钥可恢复。 每把密钥都可用密码短语备份,共分为三个包。
- 刻意保持精简。 支持 Python 3.10 至 3.14,仅需一个依赖项(
cryptography),采用 Apache-2.0 许可证。
状态: beta。0.9.0 是当前版本,也是 1.0 前的最后一个 beta 版本:每个签名都采用混合 Ed25519 + ML-DSA-65(抗量子)算法;0.8.0 部署的密钥会在首次启动时升级一次;代理后的工具可以检查自己的调用(工具检查);工具出错也会消耗其令牌;two-key setup --window 可在窗口中完成设置。0.8.0 新增了供评审器使用的近期决策摘要、账本中每位评审器的投票、每个 Agent 一个代理、只读的账本审计窗口(two-key ledger-view)和宪章编辑器。0.7.3 新增了 two-key setup,以及用于设置和更改部署的 two-key config set、get、undo 和 check;还新增了签名序列号,确保账本不会恢复到较旧规则,并会在启动器后检查上游服务的文件。0.7.0 新增了 SIEM 导出、启动检查(当被监控的 Agent 是 Two-Key 自己的账户时会拒绝运行),以及网关拒绝的令牌数量统计。
经维护者审核,并使用真实的大模型 Agent 和评审器进行测试。依赖前请阅读已知限制和 docs/FIT.md。
目录
快速开始
从 PyPI 安装 0.9.0(docs/PYPI.md):
pip install "two-key[yaml]==0.9.0"
main 上的 v0.9.0 标签对应相同代码。
也可以从克隆的仓库运行离线演示。演示使用测试替身评审器,因此无需 API 密钥:
python3 -m venv .venv
. .venv/bin/activate
pip install -e ".[yaml]"
python -m two_key demo
python -m two_key authorize --help
如需了解从安装到使用本地评审器放行和拒绝调用的十分钟操作演示,可在命令行或设置和账本窗口中查看 docs/QUICKSTART.md。
真实评审器的配置位于 examples/judges.yaml。操作指南见 docs/HOWTO.md。在真实 Agent 运行前,请封堵所有绕过 Two-Key 的途径:docs/CONNECTING.md。
在 MCP 服务前接入 Two-Key
0.5.0 版本新增(#2):
pip install "two-key[mcp]==0.9.0"
MCP 客户端(桌面助手、IDE、Agent 框架)通常会启动 MCP 服务并直接调用其工具。使用 Two-Key 时,客户端改为启动 two-key mcp-proxy。代理会自行启动真实服务,只向 Agent 展示你已签署的工具,并在服务收到调用前通过两把密钥验证每次调用。采购订单匹配等事实由你自己的钩子提供,而非来自 Agent。被拒绝的调用会以工具错误的形式返回给 Agent,并附带原因代码。
flowchart TD
host["Agent host<br/>MCP client"] -- "tools/list and<br/>tools/call, stdio" --> tk
subgraph proxy["two-key mcp-proxy, its own OS user"]
hooks["Fact hooks<br/>your code"] -- "facts" --> tk["Two-Key<br/>checks policy,<br/>asks judges"]
tk -- "token" --> gw["Gateway<br/>same process"]
end
tk -. "normalized record" .-> judges["Judges"]
gw -- "projected args,<br/>stdio" --> up["Upstream<br/>MCP server<br/>child process,<br/>third OS user"]
up --> sor["System<br/>of record"]
hooks -. "look facts up" .-> sor
two-key setup 会写入初始部署配置;two-key config set、get 和 undo 每次只更改一项设置,并在账本中进行检查和记录;config key-passphrase 会加密主体密钥(SETUP)。two-key config check --config proxy.yaml 会说明代理是否可以启动,config show 会打印其解析出的设置;两者都是只读操作(HOWTO“查看配置但不启动代理”)。two-key mcp-draft-specs 会根据服务自身的架构草拟工具规格,供你审阅和签署。包含完整示例的操作指南见 HOWTO
“在 MCP 服务前接入 Two-Key”。
代理和上游服务应以不同的操作系统用户运行,这样 Agent 和服务都无法访问代理的密钥(HOWTO“密钥保管”)。
代理仅通过 stdio 通信,不监听网络;另一台机器上的 Agent 可通过 SSH 和强制命令启动它
(CONNECTING),但此方式仍需进行实际测试。从 0.7.0 版本起,如果启动代理的账户是 Two-Key 自身账户、是 root,或能够更改 Two-Key 的文件(on_agent_access),代理将拒绝启动。
文档
| 阅读 | 适用内容 |
|---|---|
| docs/FIT.md | Two-Key 是否适合用作你的控制工具 |
| docs/QUICKSTART.md | 十分钟内完成安装,并在命令行或窗口中完成一次允许调用和一次拒绝调用 |
| docs/DEMO.md | 首次演示:通过截图逐步介绍 Two-Key 后面的 MCP 文件系统服务、Windows 上的本地 LM Studio 判定器,以及 Ubuntu 上的 Agent |
| docs/GUI_WALKTHROUGH.md | 通过一次实际运行的截图逐步介绍每个窗口:设置、宪章编辑器、账本视图,以及 0.8.0 密钥升级(0.9.0) |
| docs/HOWTO.md | 设置、配置、MCP 代理和运维 |
| docs/CONNECTING.md | 连接 Agent 和所有钩子,确保其无法绕过 Two-Key,并附有检查清单 |
| docs/SETTINGS.md | 每项设置:所在文件、默认值、high_assurance 对其的影响,以及允许修改它的人 |
| docs/SETUP.md | 首次部署时使用 two-key setup,使用 config set、get 和 undo 修改单项设置,以及使用 config key-passphrase 加密主体密钥:谁可以运行这些命令、它们会检查什么,以及会拒绝什么 |
| docs/SCANNERS.md | 使用你的防病毒或 DLP 产品进行内容扫描(0.6.0) |
| docs/SIEM.md | 将账本发送到 SIEM,并根据 SIEM 检查账本副本(0.7.0) |
| docs/TOOL_CHECK.md | 工具检查:代理后面的工具会拒绝未经过两把密钥的调用,并签署回执(0.9.0) |
| docs/AGENT_ROSTER.md | 已签名的 Agent 名册:每个 Agent 都关联到其运行所用的账户,列出每个 Agent 可使用的工具,以及来自其他厂商的判定器(0.9.0) |
| docs/LEDGER_VIEW.md | two-key ledger-view:在只读窗口中搜索、筛选和排序账本,以供审计(0.8.0) |
| docs/CONSTITUTION_EDITOR.md | two-key constitution-editor:在窗口中编写、试用并签署宪章(0.8.0) |
| docs/JUDGES_AND_QUORUM.md | 判定器如何投票,以及两把密钥如何组合使用 |
| docs/THREAT_MODEL.md | 信任边界和剩余风险 |
| docs/SCOPE.md | 包含的内容、排除的内容和计划中的内容 |
| docs/COMPARISON.md | Two-Key 不能替代什么 |
| ROADMAP.md | 通往 1.0 的路线 |
| CHANGES.md | 所有变更及升级说明 |
| SECURITY.md | 如何报告漏洞 |
| docs/UPGRADING.md | 如何升级到新版本并保留密钥和账本 |
| docs/PYPI.md | 如何注册软件包名称并发布版本 |
组件
- Constitution:由用户/管理员配置的一组签名规则(散文、硬性规则和工具规范)。由主体签署;Two-Key 强制执行签名形式。
- Policy Enforcer(路径 A):确定性的字节码策略 VM。它根据已签名的工具规范,评估从参数字节中提取的结构化字段。它不会读取自由文本或英文。
- Judge(路径 B):受信任的 AI Agent(本地或云端,最好适合具体用例)。它会为规范化的操作记录(以及可选的提案)评分。它无法直接访问任何已注册工具。
- Monitored Agent:受约束的不可信 Agent。它会提出操作,但无法直接访问任何已注册工具。
- Tool Gateway:接受一次性能力令牌并调用已注册工具。它运行在
TwoKey进程中的TwoKeyledger 对象上(TwoKey.gateway());按设计,不支持在其他进程或其他主机上运行网关(原因)。其验证器仅持有能力公钥,因此无法铸造令牌。这是 API 属性,而非密钥隔离。 - Registered Tool:受双路径授权和能力令牌保护的工具。
- MCP 代理(0.5.0;
mcpextra):two-key mcp-proxy位于 MCP 客户端与一个上游 MCP 服务之间。它只向 Agent 展示已签名的工具,固定其架构,并通过双密钥和进程内网关处理每一次tools/call。two-key mcp-draft-specs会起草工具规范,供主体审核并签署。请参阅 HOWTO《在 MCP 服务前部署 Two-Key》。 - SIEM 导出(0.7.0):ledger 可以在写入每条记录时,将其复制到 syslog 接收端或 HTTPS webhook;
two-key siem-export会将相同事件写入文件,供two-key siem-verify与 ledger 中的记录进行核对。每种类型都有字段允许列表,决定哪些内容可以导出:原因代码、摘要、大小、工具 ID 和数据类别,绝不包含参数值或提案文本。请参阅 docs/SIEM.md。 - 调用方提供的事实与 guard(0.5.0):声明为
source: caller的字段,其值来自你的集成(facts=),绝不会来自 Agent 的参数,并且会在工具运行前再次查询。two_key.guard.Guard会在一次调用中完成这两次查询和两把密钥的处理,适用于任何 Agent 循环;MCP 代理基于它运行。请参阅 HOWTO《调用方提供的事实》。
双路径授权
每次工具调用都需要先获得两个独立的“同意”才能运行。路径 A 是严格的规则检查。路径 B 是由一组 AI 评审器组成的评审组。只有两者都同意时,Two-Key 才会签发一次性通行凭证(令牌),且只有网关能使用该凭证来运行工具。
- 路径 A:规则检查(策略 VM)。
- 你的硬性规则会编译为字节码,并在一个小型虚拟机中运行。它不会读取英文,只读取结构化字段。
- 它会读取五个内置字段(
tool、amount_usd、data_class、counterparty和irreversible),以及主体在fields:下声明的任意自定义字段(布尔值、整数、枚举、字符串或路径;最多 64 个;参见 examples/custom_fields.yaml 和 HOWTO“自定义路径 A 字段”)。字段描述是供人阅读的签名备注,不是规则。 - 只要求提供工具名称。工具规格可以省略
irreversible(此时该工具视为不可逆)和data_class_floor(此时默认为classified),这两项都是安全默认值。金额和交易对象仅适用于设置了这些字段的工具。 - 如果 VM 出错,结果为拒绝。
- 值的来源。 签名后的宪章必须包含
tool_specs。如果没有该字段,就无法签名,也无法加载。Two-Key 会在 two_key/derive.py 中从调用的实际参数字节读取字段值。如果 Agent 声称的值与字节内容不一致,则拒绝该调用。 - 规格未命名的键。 这些键永远不会传递给工具。默认情况下,
deny_unmapped处于关闭状态,因此调用仍可能获准,网关只会丢弃这些键。账本会记录键名(dropped_keys),绝不记录其值。将deny_unmapped设为 true,则改为拒绝调用。 - 负载。
payload路径用于指定一个值,Two-Key 会原样传递,不作解释。它不能与金额、货币或交易对象路径相同,也不能包含在这些路径之内或位于其下方;否则规格将无法加载。如果没有设置shape,则该值下的所有内容都包含在内。shape可以将其限制为字符串、数字或字符串列表,而max_length可限制字符串或列表的长度。形状检查验证类型,不检查内容。规格不必列出所有嵌套键。 - 交易对象。 交易对象路径必须带有
allow列表。不在该列表中的对象会被拒绝,错误为counterparty_not_allowed。类似@example.org的条目(0.5.0)允许该确切域名下的所有普通地址,签名时会显示警告。工具收到的是交易对象的规范形式,而不是 Agent 发送的原始写法。 - 每个工具的自定义字段。 对于规则读取的每个自定义字段,每个工具都必须映射该字段或将其标记为
not_applicable,否则宪章无法签名(0.5.0)。设置了case: exact的字符串字段会原样保留区分大小写的 ID。 - 错误。 无法读取的值(例如
10**400)会被拒绝,错误为derive_failed。authorize内的其他错误会被拒绝,错误为internal_error:。两者都会写入账本。
- 路径 B:评审器。 你可以配置一个或多个评审器,并设置必须投赞成票的数量。
- 评审器是独立的 AI 授权端点。它们可以使用 xAI/Grok、OpenAI、Anthropic、Google Gemini、Ollama 或其他服务提供商的模型。至少需要一个评审器。每个评审器使用自己的凭据和执行上下文,不得是受监控的 Agent 本身——不得复用 Agent 的凭据和端点作为评审器。
- 缺失、格式错误、出错或超时的投票都不计为赞成票。
- 需要多少赞成票。 Two-Key 不会为你创建或选择评审器;运营方必须至少配置一个。如果未设置
required_yes,所需赞成票数为min(2, number_of_judges)。一个评审器需要一票赞成。两个或更多评审器需要两票赞成。这不是多数规则:三个评审器需要两票,四个评审器也需要两票。若要采用多数规则、一致通过或其他票数,请自行设置required_yes。 - 如果设置了
required_yes: 1且评审器不止一个,那么即使其他评审器都不可用,一个评审器也可以单独批准。TwoKey会在启动时对此发出警告,而min_responding可以弥补这一缺口。 - 评审器多样性(可选)。 默认策略没有多样性下限。
QuorumPolicy.high_assurance()(或 judges.yaml 中的profile: high_assurance)要求评审器至少来自两家模型厂商,至少有一个本地评审器,并且至少有一票赞成来自本地评审器。对于破坏性、不可逆、金融或外发工具,请使用此设置。评审器的模型厂商是其模型的制造方,由运营方标注(maker:,默认值为其provider)。这不会经过验证,并且只针对评审器制定规则:绝不会与受监控的 Agent 进行比较。如果设置了require_local_yes,但没有本地评审器,则不会启动。 - 本地的判定标准。 只有评审器自行声明为本地(
local_weights: true),且其base_url主机位于允许列表中时,才算本地:回环地址、RFC 1918 地址或 IPv6 唯一本地地址。对于任何评审器类别,:cloud/-cloud模型都不算本地模型。 - 路径 A 拒绝后。
require_path_a_first既不是下限,也不是跳过设置。派生过程拒绝后,除非设置了tool_args_on_derive_deny,否则评审器看不到参数字节。因此,如果调用无法按其规格读取(derive_failed:),在未设置该选项时就不会交给任何评审器,因为无内容可评审,账本会将路径 B 记为skipped:derive_failed。其他拒绝情形仍会交给评审器,并附带非空参数。
- 一次性通行证(能力令牌)。 只有两条路径都给出赞成结果时,Two-Key 才会签发一个短期有效、仅可使用一次的令牌。
- 令牌使用能力密钥签名,该密钥存放在账本目录之外。网关绝不会获得该私钥。
- 令牌绑定工具、参数哈希、签发时的账本 Merkle 根、宪章哈希、
spec_hash和派生形式。 - 令牌有效期为
ttl_seconds(默认值为 120,最长为 300)。 - 令牌兑换时,会先写入意图,再运行工具,因此即使发生崩溃,同一令牌也不会被使用两次。
- 网关运行工具。 网关使用能力密钥的公钥部分检查令牌。它不会持有用于创建令牌的密钥,也不会进行扫描。配置内容扫描器后(0.6.0),Two-Key 会在两条路径作出决定之前扫描调用,网关则会检查判定结果和令牌绑定的文件摘要。不会扫描工具输出。
**只要调用格式正确、未超出限制且符合其规范可读,两条路径都会作出答复。**Path A 拒绝不会跳过 Path B,因此账本会保留两者的结果。无法读取的调用(
derive_failed:)会被拒绝,不会询问裁判,除非tool_args_on_derive_deny允许裁判查看其参数。
**格式错误或超出限制的调用不会进入任一路径。**格式错误或超出限制的调用(malformed_proposal、proposal_too_large、
action_too_large、malformed_action:、args_too_large、invalid_call:)
会先被拒绝,账本中只会写入其大小和摘要。
authorize_from_agent 不会运行工具。无论 Agent 托管在本地还是云端,都不受信任。
架构
受监控的 Agent 和 Path B 裁判不会相互调用,二者都不会调用网关。调用方运行 Agent。调用格式正确且未超出限制后,Two-Key 才会运行两条路径。 只有网关会运行工具。
flowchart TD
agent["Monitored agent<br/>untrusted"] -->|"JSON proposal<br/>or decline"| authorize["Two-Key<br/>authorize"]
authorize --> early{"Declined, malformed<br/>or too big?"}
early -->|"yes"| denied["Denied<br/>no token"]
early -->|"no"| derive["Read the fields<br/>from the arguments"]
derive -. "optional scan,<br/>verdict back" .- hook["AV or DLP<br/>scanner"]
derive --> pathA["Path A: signed<br/>rules, policy VM"]
derive --> pathB["Path B: judges<br/>read the prose"]
pathA --> gate{"Both paths<br/>allow?"}
pathB --> gate
gate -->|"no"| denied
gate -->|"yes"| token["Single-use<br/>token"]
token --> gateway["Gateway<br/>runs the tool"]
denied -.-> ledger[("Encrypted ledger<br/>every step")]
gateway -.-> ledger
ledger -.->|"optional"| siem["SIEM"]
无法依据其签名规范读取的调用(derive_failed:)已由 Path A 拒绝。除非设置了 tool_args_on_derive_deny,否则裁判不会看到其原始参数(当扫描标志阻止传递参数且未设置 tool_args_on_scan_flag 时也一样),因此不会询问裁判:Path B 会被跳过,并在账本中记录为
skipped:derive_failed。跳过的 Path B 视为未通过,因此调用会被拒绝,且不会颁发令牌。
MonitoredAgent.complete 会发送章程正文和指令。
它不会收到 Path A 字节码、裁判凭据或工具凭据。只有选择加入只读
vocabulary=tk.agent_vocabulary(tools=[...]) 时,它才会收到 tool_specs:工具 ID、参数路径、值语法、下限和数据类别,但绝不会收到任何具体值(没有 allow 列表、枚举值、边界值或规则)。调用所需的确切值(例如收款方 ID)来自指令或正文(HOWTO“设计章程”)。无论哪种情况,Path A 都会检查每次调用。
它的回复是数据:tool、arguments、proposal 和可选的结构化字段,或者拒绝({"decline": "<reason>"});后者会作为 agent_declined 拒绝记录到账本,不颁发令牌,且不运行任一路径。省略
data_class 时,无论工具的下限是什么,都会视为 classified。类别以集合方式组合:personal 工具上的 medical 或 financial 仍为 medical 或 financial,两者同时存在时为 financial+medical,只有 classified 时才为 classified(HOWTO“数据类别”)。额外的键会被拒绝。authorize_from_agent 会解析该 JSON,
记录 agent id、hosting 和 trusted: false,且不会再次调用模型。这些字段是操作员/库元数据(str,strip 后最多 256 个字符);非 str 或超出长度限制都会被拒绝。托管位置为本地或云端。它不代表信任,也不会跳过任一路径。
Path A 只读取结构化字段:五个内置字段和声明的自定义字段,且这些字段都从参数字节中派生。Path B 裁判会看到规范化后的操作记录。非空工具参数会附加到该记录中,作为 tool_args,但派生拒绝时除外。在仲裁策略上设置 tool_args_on_derive_deny: true,即可无论如何都发送这些字节;未设置时,derive_failed: 调用根本不会发送给裁判。非派生拒绝的规则拒绝仍会附带参数。除非裁判设置了 receives_proposal: true,或仲裁策略为 judge_inputs: record_and_proposal,否则不会发送提案字符串。代码默认值和
examples/judges.yaml 均为 record_only。
评审器通过各自的配置和 API 密钥加载到 TwoKey 中。运营者声明受监控的 Agent(在 judges.yaml 中使用 monitored_agent:,或使用 TwoKey(monitored_agent=...)):其模型、base_url 和凭据。绝不使用该 Agent 自己的报告。启动时,TwoKey 会将每个评审器和 Agent 解析为标准化模型(折叠 Unicode 形式和短横线)、端点 host:port、为其提供服务的上游,以及该信息的获取方式(resolved_by:endpoint、model_prefix 或 declared_upstream)、限定范围的租户 ID(tenant: 映射中的 organization、project、account 或 deployment,以及 URL 中显示的内容),并使用每次安装专属的密钥生成凭据指纹,同时去除空白字符(API 令牌使用 HMAC-SHA256;用户名和密码使用 PBKDF2-HMAC-SHA256,迭代 600,000 次,并作为一对生成指纹;任何包含 : 的密钥也使用此方式)。某一方持有的每个凭据都会生成指纹,无论是否发送。
评审器可以运行任何供应商的任何模型。评审器不能是受监控的 Agent。如果评审器持有受监控 Agent 的凭据(同一 API 令牌,或同一用户名和密码),无论发送到哪个地址,TwoKey 都会拒绝启动(judge_matches_agent:):凭据无论发送到哪里,都能标识其持有者。两方都不发送凭据时,只有在相同地址(端点 host:port,本机的所有别名均折叠为 localhost)上才会被视为同一 Agent,因为没有其他信息可以区分它们。其他情况均会启动。可能的意外情况会通过 stderr 中的 two-key: WARNING: 行提示,并记录在 constitution_loaded(judge_agent_separation.warnings)中:同一地址上使用相同模型;通过共享路由,或通过未声明 upstream: 的本地或无法识别的代理访问相同模型;共享租户 ID;一方在相同地址上未配置密钥;以及无法解析上游的身份。地址按配置值比较;不会解析 DNS 名称。用户名和密码仅通过 HTTPS 以 HTTP Basic 方式发送。allow_same_provider_judge 和 allow_same_model_distinct_tenant 均可接受,但不起作用。未声明受监控的 Agent 时,系统会以 monitored_agent_required: 拒绝启动。绝不比较供应商标签。详情请参阅 HOWTO。
评审器在统一的硬性截止时间内并行投票。缺失、格式错误或超时的投票视为弃权,弃权不算赞成。没有评审器、没有截止时间,或两个评审器的 ID 相同,都无法启动。每张投票按位置与其评审器配对,并使用该评审器的 ID;如果投票中指定了其他评审器,则视为弃权(judge_id_mismatch)。缺少 agent_session 时,云端评审器会使本轮被拒绝。如果评审器不在环回主机上,或其模型名称以 :cloud 或 -cloud 结尾(无论运行在哪台主机上),则该评审器为云端评审器(通过 localhost 提供服务的 Ollama 云模型仍属于云端模型)。如果该字符串与任何评审器(本地或云端)的凭据相同,无论该评审器连接到哪里,该投票都会因 cloud_judge_reused_agent_session 而弃权,本轮也会被拒绝。每次调用都会以相同方式将受监控 Agent 的凭据与该字符串进行比较,因此占位符不会隐藏该密钥。不会将该密钥发送给评审器,也不会将其写入账本。不是该密钥的会话仍可由你传入。X-Two-Key-Judge-Session 是在此处生成的调用 ID,并非模型主机上的会话。
如果没有本地评审器,宪章正文、操作记录以及随附的任何工具参数都会发送给云端评审器的供应商。
评审器不会执行 allow 列表或数据类别;这由 Path A 负责。judges.yaml 和 agents.yaml 是受信任的运营者配置:callback 身份验证条目会导入其指定的模块,因此任何能够写入这些文件的人都能在 TwoKey 进程中运行代码。
账本中的每条 decision 都会记录 policy_digest,即生效中的法定人数策略的摘要(包括退出选项,该策略会在 constitution_loaded 中完整写入一次);还会记录 identities_digest,即已解析的评审者和 Agent 身份的摘要,这些身份会在 constitution_loaded 中写入一次:模型、上游、端点、租户 ID 和凭据指纹,绝不包含密钥。
所有 JSON 和 YAML 输入都会严格解析:任何深度出现重复键都会被拒绝,绝不会采用后者覆盖前者;YAML 合并键(<<)也会被拒绝,因为文本不会显示它的胜出值。超过 4,300 位的整数会被拒绝,或作为 invalid_call 拒绝。judges.yaml 或 agents.yaml 中未知的顶层键会被拒绝。超过 256 KiB 的工具参数或提案,或嵌套超过 62 层的工具参数、操作声明或结构化提案,会在写入账本前被拒绝。
一次调用,按代码顺序:
sequenceDiagram
participant Caller as Caller and its agent
participant TwoKey as Two-Key and Path A
participant Judges as Path B judges
participant Ledger
participant Gateway as Gateway and tool
Caller->>TwoKey: the agent's proposal, and its session
alt declined, malformed or too big
TwoKey->>Ledger: decision, with size and digest only
TwoKey-->>Caller: deny, neither path runs
end
TwoKey->>TwoKey: Path A checks the fields read from the arguments
alt the call cannot be read under its spec
Note over TwoKey,Judges: judges not asked, Path B skipped, call denied
else
TwoKey->>Judges: action record, in parallel, own credentials
Judges-->>TwoKey: yes, no, or abstain
end
TwoKey->>Ledger: proposal, Path A, Path B
alt both paths allow
TwoKey->>Ledger: capability_issued, then decision
TwoKey-->>Caller: single-use token
Caller->>Gateway: token, tool, arguments
Gateway->>Ledger: redemption_started
Gateway->>Gateway: runs the tool, in the Two-Key process
Gateway->>Ledger: redemption, or redemption_aborted
else either path denies
TwoKey->>Ledger: decision, no token
TwoKey-->>Caller: deny
end
令牌由能力密钥(<ledger>.capability/capability.pem,位于账本目录之外)签名。令牌与工具、参数哈希、签发时的账本 Merkle 根及大小、章程哈希、spec_hash 和派生形式绑定。网关通过 TwoKey.gateway() 构建(或在同一进程中使用 ToolGateway(tk.ledger, tk.issuer.verifier(), ...));无论采用哪种方式,它都只保留能力密钥的公钥部分。它会根据相同的字节重新计算形式,并检查签名、到期时间、不超过 TTL 的有效期(ttl_too_long)、最多提前 5 秒的签发时间(issued_in_future),以及签发后是否有任何内容撤销或重新加载了章程。工具运行前,它会写入 redemption_started。它不会扫描字节以查找敏感文本。主体密钥仍会为章程和账本头签名。使用主体密钥签名的令牌无法兑换;能力密钥与主体密钥相同则会被拒绝。能力密钥仅创建一次,存放在权限为 0700 的目录中,文件权限为 0600;与见证密钥一样,它只会从组用户和其他用户无法读取的常规文件中读取,绝不会通过符号链接读取。令牌一经签发,绝不会重新生成:如果密钥缺失或已更改,程序将拒绝启动。它的指纹会记录在 constitution_loaded 中,网关也会对其进行检查。
网关在 TwoKey 进程中运行,并使用 TwoKey 所用的账本对象。请使用 TwoKey.gateway() 构建网关。按设计,不支持在其他进程或其他主机上运行网关
(原因):
在其他位置打开的 Ledger 看不到打开后签发的令牌,因此会拒绝这些令牌,而且它也会持有主体密钥、见证密钥和账本密钥。若网关基于一个未由进程中的任何 TwoKey 打开的账本构建,则每个进程只会发出一次 TwoKeyDeploymentWarning。
网关的验证器只持有能力公钥,因此网关对象无法签发令牌。这是 API 层面的属性,并不代表密钥隔离。同一进程持有能力签发密钥(TwoKey.issuer),并在共享账本对象上持有主体密钥、见证密钥和账本密钥。已注册的工具也在该进程中运行。Python 不会在单个进程内提供内存隔离,因此遭到入侵的工具或依赖项可以读取上述所有密钥。请保持工具精简且可信,或将其执行的工作交由独立服务处理。
此仓库未包含的内容
本仓库不包含:
- 自有扫描、杀毒或 DLP 引擎
- 自有 SIEM、日志管理或告警产品
- 企业级部署模式和许可链锚定
- X.509 / PKI 身份和 Agent 声明
- 助记词备份
其中一些计划作为可选扩展提供。请参阅 路线图。DLP 和杀毒工具钩子已在 0.6.0 版发布(这是调用你的杀毒或 DLP 产品的接口, 而非扫描引擎: docs/SCANNERS.md)。SIEM 导出功能已在 0.7.0 版发布,它会将数据发送到你运行的收集器;它不会存储、搜索或发出告警 (docs/SIEM.md)。Ed25519 与 ML-DSA-65 混合签名 已在 0.9.0 版发布。1.0 版之后将加入带证书恢复功能的 PKI。 密钥备份已在 0.3.0 版发布,但不是助记词备份。企业级部署模式、许可链锚定和助记词 均不在计划之列。
账本在静态存储时经过加密。
此处的加密算法采用 Ed25519 与 ML-DSA-65 混合签名(自 0.9.0 版起),并通过
cryptography 软件包使用 SHA-256。账本
条目和已签名的头部在静态存储时采用 AES-256-GCM 加密。数据密钥由账本目录之外的账本密钥封装,
而非由主体密钥封装。头部由主体和见证密钥签名,见证密钥也位于账本目录之外。仅窃取主体密钥
无法解密日志或签署新头部。见证公钥固定在账本中(作为第一条目
witness_pinned),因此会拒绝被替换的 witness.pem
(witness_key_changed)。如果同时取得账本密钥,主体密钥仍可从第一条目起重写整条链,包括固定的见证公钥,除非
操作员也将见证公钥作为配置提供
(Ledger(..., witness_public_key=...) 或 --witness-public-key),并将其保存在无法由能写入账本目录的人更改的位置。
设置此固定公钥后,伪造头部需要同时取得主体密钥、见证密钥和账本密钥。见证密钥只能通过记入账本的轮换操作更改(two-key rotate-witness)。
状态:测试版(1.0 之前)。本项目经过维护者审查,并进行了实时 LLM 测试和自动扫描(Semgrep、DeepSource、Bandit、CodeQL),但尚未经过独立审计。所有使用的算法均获 FIPS 批准;待通过验证的模块提供 ML-DSA-65 后,将推出 FIPS 140-3 批准模式(请参阅已知限制)。
已知限制
- 未经独立审查,也未部署到生产环境。
- Two-Key 会验证实际执行的调用是否与两把密钥批准的调用一致。
但不会验证 Agent 声称的事实:从参数读取的自定义字段(例如
po_matched: true)只是 Agent 的说法。工具 或集成必须根据权威数据源检查此类事实(HOWTO“Two-Key 验证的内容”)。从 0.5.0 起,source: caller字段会改为从集成自身的查询中获取事实;该事实的可靠性取决于查询本身,Two-Key 不会检查查询结果。 - 没有账本的外部锚点。持有主体密钥和账本密钥的人可以重写从未离开本机的账本,除非
在账本之外配置了见证公钥(
--witness-public-key);此时还需要见证密钥(#58)。 账本目录之外的头部锚点 (<ledger>.ledger-key/head.anchor,或--head-anchor)会拒绝仅回滚账本或 清除账本目录的操作(#62)。如果锚点与账本一同被删除或回滚,则不会拒绝。能够写入锚点文件的人仍可执行这两种操作。它不是外部锚点。 - FIPS 140-3:所有算法均获 FIPS 批准(FIPS 204 下的 ML-DSA-65、FIPS 186-5 下的 Ed25519、AES-256-GCM、SHA-256、HMAC、HKDF、PBKDF2),但来自 PyPI 的
cryptography轮子并非经过验证的模块。只有当某个经过验证的模块支持 ML-DSA-65 后,才能以经过批准的模式运行:OpenSSL 3.5 是首个支持 ML-DSA 的 OpenSSL 版本;其 FIPS 提供程序正在 NIST 的验证队列中(于 2025 年 10 月提交,截至 2026-10-29 尚无证书),而经过验证的 OpenSSL 3.1.2(证书 #4985)不支持 ML-DSA。Two-Key 不会为了更早实现这一点而弃用 ML-DSA-65。 - 从 0.9.0 起,签名采用 Ed25519 与 ML-DSA-65(FIPS 204)的混合方案,只有两部分都通过验证才算有效,因此即使量子计算机破解了 Ed25519,也无法仅凭此伪造签名。对于这些密钥长度,AES-256-GCM 和 SHA-256 并非问题所在。与评审者和上游服务之间的 TLS 不在 Two-Key 的保护范围内。0.8.0 部署的密钥会在首次启动时升级一次 (docs/UPGRADING.md)。
- 身份仅由裸密钥表示。没有证书链、有效期或吊销机制。支持证书恢复的 PKI 已列入路线图。
- 它不是杀毒软件或 DLP 产品。从 0.6.0 起,它可以 调用你运行的扫描器(docs/SCANNERS.md)。如果没有扫描器,自由文本中的内容泄露风险由评审者承担。工具结果绝不会被扫描。
- 它不是 SIEM。从 0.7.0 起,它可以通过默认启用的 TLS,将每条账本记录发送到你运行的收集器;在
high_assurance模式下会拒绝明文接收端,否则会发出警告。任何能读取该收集器的人都能读取账本元数据;如果收集器宕机,副本会留存,直到收集器恢复;收集器保留哪些内容或针对哪些内容发出警报,由你负责,而非 Two-Key(docs/SIEM.md)。 - 在 MCP 代理后方,如果 Agent 能直接访问上游服务,就可以绕过代理,除非工具自行检查每次调用 (docs/TOOL_CHECK.md,0.9.0);而以代理的操作系统用户身份运行的上游服务可以读取代理的密钥。请让两者分别以各自的用户身份运行(HOWTO“密钥保管”)。
- 密钥备份的强度取决于其密码短语。备份包就是密钥本身。
PBKDF2 会增加猜测难度,但不具备内存困难特性。它不是种子短语,
也不是外部锚点。恢复到较新的账本时,会补齐缺失的密钥文件,并保留已有密钥。
--replace-ledger可能导致备份后已花费的令牌看起来尚未花费,并会替换内容不同的密钥文件。
完整清单见 docs/THREAT_MODEL.md。
路线图
MCP 适配器已在 0.5.0 发布;Windows 支持、DLP 和防病毒钩子,以及裁决器连接复用已在 0.6.0 发布。用于 SIEM 的账本导出已在 0.7.0 发布,设置和变更命令以及签名序列号已在 0.7.3 发布,裁决器历史摘要则已在 0.8.0 发布。最后一个 beta 版本 0.9.0 带来了混合签名、工具检查和签名 Agent 名册。接下来是 0.9.1,然后进行公开评审并发布首个稳定版 1.0。 这表达的是意向,而非承诺:顺序可能会变,版本号是目标,而非日期。详情以及 1.0 之后的规划,请见 ROADMAP.md。
flowchart TD
subgraph done["Released betas"]
direction LR
r04["0.4.0<br/>Package<br/>two-key"] --> r05["0.5.0<br/>MCP<br/>adapter"] --> r06["0.6.0<br/>DLP and AV<br/>hooks"] --> r07["0.7.0<br/>SIEM<br/>export"] --> r073["0.7.3<br/>Setup<br/>commands"] --> r08["0.8.0<br/>Judge<br/>history"] --> r09["0.9.0<br/>Tool check,<br/>agent roster,<br/>hybrid<br/>signatures"]
end
subgraph next["Next: 0.9.1, then 1.0.0"]
direction LR
r091["0.9.1<br/>TS helper,<br/>fixes"] --> r10["1.0.0<br/>SSH live run,<br/>1.0 freeze,<br/>stable release"] -.-> after["After 1.0<br/>PKI, FIPS mode,<br/>more GUI"]
end
done --> next
| 版本 | 内容 | 状态 |
|---|---|---|
| 0.4.0 | 此代码库和软件包名称 two-key | 已发布,标签 v0.4.0 |
| 0.5.0 | MCP 代理和规范起草器、调用方提供的事实、守护核心 | 已发布,标签 v0.5.0 |
| 0.6.0 | Windows 支持;调用外部扫描器(ClamAV、ICAP 产品、命令、Python)的 DLP 和防病毒钩子;裁决器连接复用(#6) | 已发布,标签 v0.6.0 |
| 0.7.0 | 用于 SIEM 的账本导出:实时 syslog 或 webhook 投递,以及经过验证的文件导出,不含参数值;在账本之外保留拒绝令牌的计数 | 已发布,标签 v0.7.0 |
| 0.7.3 | two-key setup 和 config set、get、undo、show 与 check;带口令的主体密钥;用于防止旧规则的签名序列号;启动器后面的上游服务文件(#13) | 已发布,标签 v0.7.3 |
| 0.8.0 | 裁决器历史摘要(#1)、逐个裁决器的投票记录、每个 Agent 一个代理、账本审计窗口和宪章编辑器 | 已发布,标签 v0.8.0 |
| 0.9.0 | 最后一个 beta:混合 Ed25519 和 ML-DSA-65 签名、可选的工具检查(#28)、签名 Agent 名册、密钥一的文件夹路径规则、设置窗口和快速入门 | 已发布,标签 v0.9.0 |
| 0.9.1 | TypeScript 工具检查辅助程序,以及根据 0.9.0 评审修复的问题 | 计划中 |
| 1.0.0 | 首个稳定版;需先通过 SSH 在另一台机器上与 Agent 进行一次实际运行,并对 0.9.0 进行公开社区评审;UPGRADING.md 中会说明 1.0 保持稳定的内容。称为经社区评审,而非经审计。首次 PyPI 上传版本为 0.7.0 | 计划中 |
| 1.0 之后 | PKI 和证书恢复;经验证的模块支持 ML-DSA-65 后提供 FIPS 140-3 批准模式;其余本地 GUI(账本视图、宪章编辑器和设置窗口将在 1.0 之前推出);可选的信誉暂停机制;更多规范字段类型 | 尚未排期 |
安装和版本
Two-Key 可在 Linux、macOS 上运行,并从 0.6.0 起支持 Windows,三个平台均配置了 CI(HOWTO「Platforms」)。0.9.0 版本已发布到 PyPI。这是 beta 版本,并非 1.0 社区评审版。标签不会移动。
pip install "two-key[yaml]==0.9.0"
v0.9.0 使用混合 Ed25519 + ML-DSA-65 密钥为所有内容签名,并为 0.8.0 部署升级一次密钥;新增工具检查,在工具出错时消耗一个令牌,并新增设置窗口。@v0.8.0 向评审者提供近期决策摘要,将每位评审者的投票保存在账本中,让每个 Agent 可由一个代理提供服务,并新增账本审计窗口和章程编辑器。@v0.7.3 新增 two-key setup 和 config 命令、使用密码短语加密的主体密钥、用于确保账本不会回退到旧规则的已签名序列号,以及对上游服务文件的启动检查。
main 包含该版本及之后合并的修复;下一轮更改会进入 working。@v0.7.0 包含用于 SIEM 的账本导出、针对受监控 Agent 运行所用账户的启动检查,以及网关拒绝的令牌数量统计。PyPI 上的 0.7.1 和 0.7.2 是重新打包的 0.7.0 代码。要使用更早的版本,请选择 @v0.6.0:支持 Windows、可调用你的防病毒或 DLP 产品(ClamAV、ICAP、命令或 Python)的内容扫描、针对其他账户可更改路径的启动检查,以及评审者连接复用。@v0.5.0 包含 MCP 代理、规范草案生成器、调用方提供的事实、守护核心和章程 v3。@v0.4.0 是使用新包名 two-key 的 0.3.1 代码。标签 v0.3.1 及更早版本位于已归档的 two-key-concept 仓库中,其中 v0.3.0 对应 e44be56,v0.2.4 对应 fc836bb,v0.2.3 对应 4a4352e,v0.2.0 对应 2f756ac。
从旧版本升级:请阅读 CHANGES.md 中每个跳过版本的“升级”说明。
- 0.2.3 不再接受
vendor:和min_vendors:键;对于 0.2.2 接受的某些判断器,它会拒绝(无论是持有 Agent 凭据但不发送凭据的判断器,还是另一种形式的判断器),并会在首次打开时固定每个账本的见证密钥:“从 0.2.2 升级”(以及旧版本中的“从 0.2.1 升级”和“从 0.1.12 升级”)。 - 0.2.4 会在首次打开现有账本时写入头部锚点,并拒绝已回滚的账本目录:“从 0.2.3 升级”。
- 0.3.0 新增密钥备份、自定义 Path A 字段和
TwoKey.gateway()(为何它在进程内运行)。现有账本和章程可原样打开:“从 0.2.4 升级”。声明自定义字段的章程会以 v2 格式签名,而 0.3.0 之前安装的版本会拒绝该格式:“自定义 Path A 字段” > “升级”。 - 0.3.1 更改了数据类的组合方式,并新增 Agent 拒绝操作:“版本 v0.3.1” > “升级”。
- 0.4.0 重命名了软件包及其文件格式。密钥文件仍可加载;请重新签署章程、启动新账本并导出新的备份:“从 0.3.1 升级”。
- 0.5.0 新增章程 v3,用于调用方提供的事实和第 6 轮后续操作。升级前请检查:如果某个工具既未映射规则读取的字段,也未将其标记为
not_applicable,那么相应章程将无法再加载;以@开头的allow条目现在表示整个域。无法根据其规范读取的调用不再发送给判断器。“从 0.4.0 升级”和 CHANGES.md 中的第 6 轮条目。 - 0.6.0 可原样加载 0.5.0 章程、账本、密钥和
proxy.yaml文件。升级前请检查:启动时会列出运行或读取的、且可能被其他账户更改的每个文件或文件夹;在high_assurance模式下,如果存在此类文件或文件夹,则拒绝启动。“版本 v0.6.0” > CHANGES.md 中的“从 0.5.0 升级”。 - 0.7.0 可原样加载 0.6.0 章程、账本、密钥和
proxy.yaml文件;未设置siem时不会发送任何内容。升级前请检查:在high_assurance模式下,明文 syslog 接收端(udp或tcp)会导致启动被拒绝;如果受监控 Agent 以 Two-Key 自身账户运行,或能够更改 Two-Key 文件,代理也会拒绝启动。“版本 v0.7.0” > CHANGES.md 中的“从 0.6.0 升级”。 - 0.7.3 可原样加载 0.7.0 章程、账本、密钥和
proxy.yaml文件。升级前请检查:代理现在会检查upstream.command中指定的上游服务文件;如果sudo或npx等启动器隐藏了这些文件,则会发出警告(在high_assurance模式下则拒绝启动);账本一旦运行过带有serial的章程,就会拒绝较旧的章程。“版本 v0.7.3” > CHANGES.md 中的“从 0.7.0 升级”。 - 0.8.0 可原样加载 0.7.3 章程、密钥、账本和
proxy.yaml文件。升级前请检查:判断器现在会收到历史摘要(默认启用);同一账本上为同一 Agent 启动第二个代理会被拒绝;使用云端判断器的代理需要设置agent_session_env。请保留升级前的账本备份。“版本 v0.8.0” > CHANGES.md 中的“从 0.7.3 升级”。 - 0.9.0 会在 0.8.0 部署首次启动时,将其密钥一次性升级为混合 Ed25519 + ML-DSA-65 密钥,且无法回退:此后 0.8.0 将无法打开该账本。它需要
cryptography48 或更高版本。请在升级前和升级后立即各备份一次。直接调用TwoKey的代码在运行一次two-key keys upgrade之前,会拒绝 0.8.0 密钥。升级文档“从 0.8.0 到 0.9.0,逐步操作”以及 CHANGES.md 中的“从 0.8.0 升级”。
使用 pip install -e 安装的克隆版本遵循 pyproject.toml 中的版本范围。CI 则不同:它只安装 uv.lock 中指定版本的 wheel(cryptography、PyYAML、mcp extra 对应的 MCP SDK 及其依赖)。若要与 CI 保持一致,请使用 .github/requirements/uv.in 中固定的 uv 版本:
pip install --only-binary :all: "uv==0.13.5"
uv sync --locked --no-build --extra yaml --extra mcp --no-dev
.venv/bin/python -m unittest discover -s tests
目录结构
GitHub 文件列表中的中间列显示的是最近一次修改该文件的提交,而不是文件说明。此表才是文件说明。
| 路径 | 内容 |
|---|---|
two_key/core.py | TwoKey.authorize 和 authorize_from_agent |
two_key/history.py | 根据账本构建的裁决者历史摘要(0.8.0) |
two_key/audit.py | check_decision_digests:重新计算每项决策的 identities_digest 和 policy_digest |
two_key/policy_vm.py、compiler.py | 路径 A |
two_key/derive.py | 为路径 A 的表单推导工具规范 |
two_key/fields.py | 自定义路径 A 字段:注册表、类型、字符集、限制 |
two_key/quorum.py、two_key/judges/ | 路径 B 和裁决者传输 |
two_key/identity.py、netloc.py | 检查裁决者 ≠ 受监控 Agent;本地主机与云主机 |
two_key/strict.py | 严格加载 JSON 和 YAML(拒绝重复键、合并键和超大整数) |
two_key/agents.py | 受监控 Agent 钩子 |
two_key/ledger.py | 加密账本;账本密钥和见证文件位于该目录之外 |
two_key/capability.py、gateway.py | 令牌和兑换。网关只负责验证。 |
two_key/toolcheck.py | 工具检查:兑换印章、工具端检查及其回执(0.9.0) |
two_key/guard.py | 通过两把密钥执行一次受保护的调用,并使用调用方提供的事实钩子(适用于任何 Agent 循环;MCP 代理会使用它) |
two_key/siem.py、siem_sinks.py、siem_export.py | SIEM 导出:按类型划分的字段允许列表和架构、syslog 和 webhook 接收器,以及文件导出及其离线检查 |
two_key/scan.py、scanners.py | 内容扫描:核心模块,以及适用于 ClamAV、ICAP、命令和 Python 的适配器 |
two_key/_platform.py、writable.py | 在 POSIX 和 Windows 上使用仅所有者可访问的文件、锁和禁止跟随符号链接的打开方式;启动时检查其他账户可能更改的路径 |
two_key/mcp_proxy/ | MCP 代理和规范起草工具(mcp extra)。config.py 和 core.py 负责决策;只有 sdk.py 会导入 MCP SDK;draft.py 用于起草规范 |
two_key/keys.py、cli.py、backup.py | 密钥文件(从 0.9.0 起采用混合 Ed25519 + ML-DSA-65);two-key 命令行;对软件包自身密钥进行口令短语备份 |
two_key/upgrade.py | 对 0.8.0 部署执行一次性密钥升级(keys_upgraded,0.9.0) |
two_key/setup_cmd.py、setup_form.py、setup_gui.py | two-key setup:问题、两个前端共用的检查,以及设置窗口(0.9.0) |
two_key/config_cmd.py、config_set.py、settings.py | two-key config check、show、get、set、undo 和 key-passphrase,以及所有设置的注册表 |
two_key/ledger_view.py、ledger_gui.py | two-key ledger-view:搜索和只读窗口 |
two_key/constitution_editor.py、constitution_gui.py | two-key constitution-editor:检查、试运行调用、签名和窗口 |
two_key/action.py | 规范化操作记录及其验证 |
two_key/agent_meta.py | 对写入账本的操作员或库提供的 Agent 身份元数据进行限制 |
two_key/canonical.py | 账本、令牌和裁决者绑定的规范编码 |
two_key/constitution.py | 签名宪章:路径 B 的文字、路径 A 的硬性规则和工具规范 |
two_key/testing.py | 仅用于离线测试的替身;并非真实裁决者 |
examples/ | 宪章、硬性规则、自定义字段、裁决者、Agent 和 Elastic SIEM 示例 |
pyproject.toml | 软件包名称 two-key、版本、依赖项、extras 和 two-key 命令 |
MANIFEST.in | 源码分发包中包含的文档和示例。wheel 中仅包含 two_key |
docs/PYPI.md | 如何注册名称并通过可信发布进行发布,且无需在仓库中放置令牌 |
.github/workflows/pypi-publish.yml | 构建、元数据检查、SBOM 和无令牌上传。该文件位于 main;只有在 PyPI 分支上手动启动运行时才会发布 |
.github/workflows/mcp-registry.yml | 使用 server.json 将此版本列入官方 MCP Registry,并通过 GitHub Actions OIDC 签入。在 PyPI 上传后,于 PyPI 分支上手动启动 |
历史记录和许可证
开发工作于 0.3.1 版本从已归档的 two-key-concept 仓库迁移至此;其历史记录已保留在本仓库中。
Apache License 2.0。请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。