本机云厂商 LLM Key 经 nanomesh P2P 共享方案
一句话:你在本机购买的大模型 API Key(OpenAI / Anthropic / DeepSeek …)只保存在本机;
通过 nanomesh 注册为可发现的 model.llm 能力,并对外提供 model.infer / model.stream;
其他用户电脑上的 Codex、Claude Code、Qoder、WorkBuddy 等智能体,只需把
OPENAI_BASE_URL 指到本机 nm-llm-proxy,即可经 P2P 使用你这边的模型能力——Key 永不离开你的电脑。
状态:草案 v1(2026-10-24)。与 COMPUTE_MODEL_P2P_DESIGN.md(通用算力/模型实体)、
CMX_AGENT_MERGE_DESIGN.md(内置 Agent 的 P2pModelSeam)对齐,本文件聚焦「云 Key 代理 + 智能体 HTTP 兼容接入」。
0. 目标 / 非目标
目标
非目标(本期不做)
- 不做链上结算 / 去信任计费(先做计量与配额;计费层后接 PLAN_E)。
- 不做对提供方保密的 prompt(提供方必须见明文才能转发云 API;TEE 属后续)。
- 不强制所有智能体改造成原生 nm-client(内置 Agent 可走 P2pModelSeam;第三方工具走 HTTP proxy)。
1. 场景总览
角色
| 提供方主机 | nmd + nm-llm-gatewayd | 云厂商 API Key |
| 消费方主机 | nmd/nm-client + nm-llm-proxy + Codex/Claude Code/… | 本地 proxy token + Grant |
| nanomesh 网络 | iroh QUIC / relay.robot.link | 目录、投递、验签 |
2. 为什么用 nanomesh 而不是「直接分享 Key」
| 把 Key 明文发给朋友 | Key 泄露、无法吊销单用户、无法计量 |
| 自建中心化反向代理 | 单点、需公网 IP、与去中心网格割裂 |
| 本方案:P2P 能力实体 | Key 不出境;按公钥授权;目录发现;与现有 model.infer / Grant 一致 |
已有原语(见 COMPUTE_MODEL_P2P_DESIGN.md):
- 实体 kind=model.llm + directory_query
- Client::call / Session::next_command + model.infer
- issue_grant / Command.grant
- OpenAI JSON 载荷约定:type_url = "openai.chat.v1"(nm-client::Session::infer 已实现)
3. 端到端调用时序
4. 组件拆分
4.1 nm-llm-gatewayd(提供方)
新建 bin/nm-llm-gatewayd(或并入现有 compute agent 形态):
| 身份 | nm-client online 到本机/指定 home nmd |
| 注册 | register_as → kind=model.llm,attributes 含 provider/model/models/auth=grant |
| 接单 | 循环 next_command,处理 model.infer / model.stream |
| 出站 | reqwest/OpenSSL 调云厂商;Key 仅内存 + OS keyring |
| 门禁 | 验 Grant;QPS / 日 token 配额;可选 IP/好友白名单 |
| 计量 | 本地 SQLite 记 (consumer_id, model, tokens, ts);可 TELEMETRY_PUB |
配置示例(提供方)
# ~/.config/nanomesh/llm-gateway.toml
home_node = "<本机 nmd 公钥或 NM_NODE_ADDR>"
display_name = "cmxlinux-openai-share"
[[backends]]
id = "openai-main"
provider = "openai" # openai | anthropic | deepseek | custom
base_url = "https://api.openai.com/v1"
# key 从环境变量或 keyring 读取,禁止写入 toml 明文
key_env = "OPENAI_API_KEY"
models = ["gpt-4o", "gpt-4o-mini"]
[policy]
require_grant = true
# 允许的消费方公钥(空 = 仅手动签发 Grant 的 audience)
allow_audiences = ["<friend_pubkey_hex>", "…"]
daily_token_budget = 2_000_000
max_concurrent = 4
4.2 nm-llm-proxy(消费方)
轻量本地 HTTP 服务(可 Rust 二进制或小 Node 服务,推荐 Rust 与仓库一致):
| GET /v1/models | 聚合目录中可见的 model.llm |
| POST /v1/chat/completions | 同步 / stream:true → SSE |
| POST /anthropic/v1/messages(P2) | 映射到同一 P2P 调用 |
智能体侧环境变量(消费方)
export OPENAI_BASE_URL=http://127.0.0.1:11434/v1
export OPENAI_API_KEY=nm-local-token # 仅校验本地 proxy,不是云 Key
# 可选:固定某提供方实体
export NM_LLM_PROVIDER_ID=<64-hex>
4.3 与内置 Agent 的关系
- 第三方工具(Codex / Claude Code / …)→ 必须走 nm-llm-proxy(它们只会 HTTP)。
- nanomesh 内置 Agent(CMX_AGENT_MERGE_DESIGN.md)→ 可直接 P2pModelSeam → Session::infer,绕过 proxy,少一跳。
5. 智能体接入映射
原则:智能体以为自己连的是「本机 OpenAI 兼容服务」;P2P 对它们透明。
6. 协议约定(与现有代码对齐)
6.1 发现
directory_query(
kind_prefix = "model.",
require_capabilities = [COMMAND], # 流式再加 STREAM
match_attributes = { "model": "gpt-4o" } # 可选
)
云 Key 代理建议 attributes:
| provider | openai | 云厂商 |
| model / models | gpt-4o / a,b,c | 可服务模型 |
| auth | grant | 需要 Grant |
| proxy | cloud | 区分于本地 ollama |
| status / load | idle / 30 | 撮合 |
6.2 调用
复用已有:
// 消费端(proxy 内部)
session.infer_with_grant(provider_id, openai_request_json, Some(grant)).await?;
// type_url = "openai.chat.v1"(Session::infer 已写死)
提供端:
next_command → method == "model.infer"
→ decode openai.chat.v1
→ HTTP 调云
→ reply(ok, Any{type_url: openai.chat.completion.v1, value})
流式(P1):model.stream 或同一 method + stream=true,用 uni 流 / 临时频道回推 chunk(对齐 COMPUTE 方案 §4)。
6.3 授权
issue_grant(
audience = consumer_pubkey,
action = "model.infer",
resource = "model:gpt-4o", # 或 model:*
expires = now + 7d
)
提供方 authorize(grant, caller, "model.infer", "model.llm", now);失败则 CommandResult.ok=false。
7. 安全设计
| Key 泄露给消费方 | Key 只在 gatewayd;proxy 无 Key |
| 未授权调用 | Grant 验签 + audience 白名单 |
| 超额刷量 | 日配额 / 并发上限 / 按 consumer 记账 |
| 恶意 prompt 攻击提供方账号 | 内容策略可选;异常用量告警;可一键吊销 Grant |
| 中间人读流量 | iroh QUIC;管理面勿把 Key 打进日志 |
| 提供方作恶读 prompt | 明示信任模型:共享 = 信任该主机主人;UI 强提示 |
Key 存储:优先 OS keyring(与桌面端设备口令同路径);禁止提交 git / 禁止出现在联邦同步的 redb 明文。
8. 部署与里程碑
| P0 | nm-llm-gatewayd(OpenAI 同步)+ nm-llm-proxy + 好友 Grant | 机器 A 持 Key;机器 B 跑 Codex,BASE_URL 指本地 proxy,能完成一轮补全 |
| P1 | SSE 流式、配额、审计、多 model attributes、failover | Claude Code 长对话流式稳定;超配额被拒 |
| P2 | Anthropic 映射、多厂商、桌面「共享开关」UI | Qoder/WorkBuddy 等同配置可用 |
| P3 | 计费/Broker/滥用检测 | 与 PLAN_E 衔接 |
建议仓库落点
bin/nm-llm-gatewayd/ # 提供方
bin/nm-llm-proxy/ # 消费方(也可 crates/nm-llm-proxy + 薄 bin)
crates/nm-llm-openai/ # 请求/响应映射、SSE 编解码(可选抽出)
docs/LLM_KEY_SHARE_P2P_DESIGN.md # 本文
复用:nm-client 的 find_model_providers / infer_with_grant(已存在)。
9. 本机 / 远端操作手册(P0 预览)
提供方(持 Key)
# 1. 本机 nmd 已运行
# 2. 写入 Key(示例)
export OPENAI_API_KEY=sk-...
# 3. 启动网关
cargo run -p nm-llm-gatewayd — –config ~/.config/nanomesh/llm-gateway.toml
# 4. 给好友签发 Grant(CLI 或管理台后续做)
nm-llm-grant –audience <friend_hex> –model gpt-4o –days 7
消费方(跑智能体)
# 1. 本机可连联邦(nmd 或桌面端在线)
# 2. 启动 proxy
cargo run -p nm-llm-proxy — –listen 127.0.0.1:11434
# 3. 配置智能体
export OPENAI_BASE_URL=http://127.0.0.1:11434/v1
export OPENAI_API_KEY=nm-local-token
# 4. 正常使用 Codex / Claude Code / …
10. 风险与开放问题
11. 决策清单(待评审勾选)
- P0 是否只支持 OpenAI 兼容一种载荷(openai.chat.v1)?
- Grant 默认策略:好友自动授 / 手动签发 / 口令兑换?
- proxy 默认端口 11434(贴近 ollama)还是 18080?
- gatewayd 是否并入现有 nm-agent/nm-compute 二进制,还是独立 bin?
- 桌面端是否在设置页增加「共享我的云模型」开关(P2)?
12. 参考
- docs/COMPUTE_MODEL_P2P_DESIGN.md — 通用 model/compute P2P
- docs/CMX_AGENT_MERGE_DESIGN.md — 内置 Agent × P2pModelSeam
- docs/PLAN_E_decentralized_compute_network.md — 长期 DePIN / 结算
- crates/nm-client/src/session_calls.rs — find_model_providers / infer_with_grant
- crates/nm-crypto — Grant 签发与校验
网硕互联帮助中心




评论前必须登录!
注册