@antseed/节点
AntSeed的核心协议SDK——对等的AI服务网络. 供应商提供AI服务,买方通过DHT发现供应商,并通过加密的P2P连接发送请求.
重要内容: AntSeed是为在AI API之上建立有区别服务的提供者设计的——如TEE安全推论,特定域的技能和代理,微调模型,或管理出的产品体验等. 简单转售原始API访问或订阅证书不是预定用途,可能违反你上游供应商的服务条款.
安装
npm install @antseed/node
快速启动
提供者模式
供应商节点在DHT上宣布其容量,并服务于买方的推断请求.
import { AntseedNode } from '@antseed/node';
import type { Provider, SerializedHttpRequest, SerializedHttpResponse } from '@antseed/node';
// Implement the Provider interface (or use an existing plugin)
const myProvider: Provider = {
name: 'my-llm',
services: ['my-model-v1'],
pricing: {
defaults: {
inputUsdPerMillion: 10,
cachedInputUsdPerMillion: 1, // optional, defaults to inputUsdPerMillion
outputUsdPerMillion: 10,
},
},
serviceCategories: {
'my-model-v1': ['coding', 'privacy'],
},
maxConcurrency: 10,
async handleRequest(req: SerializedHttpRequest): Promise<SerializedHttpResponse> {
// Forward the request to your LLM backend and return the response
const result = await callMyBackend(req);
return {
requestId: req.requestId,
statusCode: 200,
headers: { 'content-type': 'application/json' },
body: new TextEncoder().encode(JSON.stringify(result)),
};
},
getCapacity() {
return { current: 0, max: 10 };
},
};
const node = new AntseedNode({ role: 'seller' });
node.registerProvider(myProvider);
await node.start();
console.log('Seller peer ID:', node.peerId);
// Node is now discoverable on the DHT and accepting P2P connections
买家模式
买方节点通过DHT发现卖方,与之连接,并发出推断请求.
import { AntseedNode } from '@antseed/node';
import { randomUUID } from 'node:crypto';
const node = new AntseedNode({ role: 'buyer' });
await node.start();
// Discover sellers on the network
const peers = await node.discoverPeers();
if (peers.length > 0) {
const seller = peers[0];
const response = await node.sendRequest(seller, {
requestId: randomUUID(),
method: 'POST',
path: '/v1/messages',
headers: { 'content-type': 'application/json' },
body: new TextEncoder().encode(JSON.stringify({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 256,
messages: [{ role: 'user', content: 'Hello' }],
})),
});
console.log('Response status:', response.statusCode);
}
发现主题正常化
发现主题实现正常化,以提高搜索的一致性:
- 提供者主题 :
antseed:{provider}与trim + lowercase - 模型主题( 分类):
antseed:service:{model}与trim + lowercase - 模型主题( 搜索倒计时) :
antseed:service-search:{model}有空间,-, (中文(简体) ),_犬科正常化后删除(保留).(中文(简体) )
分类和搜索模型主题在键不同时都使用,因此变体如 kimi 2.5, (中文(简体) ), kimi-2.5,以及 kimi_2.5 可以在发现中凝聚,同时保留精确的犬科主题.
安全概览
完整的买方-卖方威胁模型和硬化指南见:
在高层, @antseed/node 目前执行 :
- 已签名的发现元数据核查和Stalety检查
- 带有回放保护功能的已签名的内接信封
- 框架、流和上传限制以减少 DoS 曝光
- 了解付款请求
402如果启用付款时没有保留会话) - 签署的双边收据(sepp256k1)加链上付款授权(ECDSA)
节点配置
interface NodeConfig {
role: 'seller' | 'buyer';
displayName?: string; // Optional human-readable name announced in metadata
publicAddress?: string; // Optional public host:port override announced in metadata
dataDir?: string; // Default: ~/.antseed
identityStore?: IdentityStore; // Pluggable identity storage backend
dhtPort?: number; // Default: 6881 for seller, 0 (OS-assigned) for buyer
signalingPort?: number; // Default: 6882 for seller
maxUploadBodyBytes?: number; // Default: 64 MiB per request
bootstrapNodes?: Array<{ host: string; port: number }>;
payments?: {
enabled?: boolean;
paymentMethod?: 'crypto';
settlementIdleMs?: number;
defaultSessionAmountUSDC?: string;
sellerWalletAddress?: string;
paymentConfig?: PaymentConfig | null;
};
}
| 选项 | 默认 | 说明 |
|---|---|---|
role | (必须) | 'seller' 满足请求, 'buyer' 来消耗它们 |
displayName | 未设定 | 发现元数据中包含的可选节点标签 |
publicAddress | 未设定 | 可选公众 host:port 在已签名的元数据中进行广告宣传,且买方优于原始 DHT 源地址 |
dataDir | ~/.antseed | 身份密钥、 计量 DB 和配置目录 |
identityStore | FileIdentityStore | 可插件身份存储后端( 见 身份存储(中文(简体) ) |
dhtPort | 6881 编号 : 0 | DHT的UDP端口. 卖方违约为6881起,买方使用OS指定 |
signalingPort | 6882 | P2P 信号和接通连接的 TCP 端口( 只售出) |
maxUploadBodyBytes | 64 MiB | 卖方接受每个代理上传的最大请求体。 高高的代码样式 /v1/responses 有效载荷,同时保持待加载总预算的限度. |
bootstrapNodes | 蚂蚁种子节点 | DHT靴子节点与正式的AntSeed基础设施合并 |
payments | 已禁用 | 可选售方付款渠道+结算寿命周期线 |
使用 publicAddress 当DHT宣布源IP不是地址购买者应该拨号时,例如Kubernetes或其他负载平衡部署:
const node = new AntseedNode({
role: 'seller',
publicAddress: 'peer.example.com:6882',
});
身份存储
每个节点都有一个 secp256k1 身份键帕。 私钥(32字节,以64个十六进制字符存储)服务于两个角色:
- P2P 身份标识 ——签署元数据,接通握手,并进行计量收取. 您的 PeerId 是来自公钥的 EVM 地址( 40 十六个字符) .
- 链上钱包 ——同一secp256k1键被作为EVM钱包使用. 该钱包持有存款、股份、收取销售收入并签署付款授权书.
重要内容: 失去身份密钥意味着失去同伴身份和获取任何与衍生钱包挂钩的链上资金.
存储后端
身份加载遵循此优先级:
- 环境变量(CLI/服务器推荐) 如果
ANTSEED_IDENTITY_HEX设置( 64 十六进制字符, 可选)0x前缀),它直接被使用,读取后立即清除出环境. 用此与秘密管理人员进行生产部署. - 桌面密钥链( 建议用于桌面) – AntSeed 桌面通过 Electron 加密休息时的密钥
safeStorage和 OS 键链(macOS keychain / Windows DAPI / Linux libsect). - 自定义身份 如果
identityStore被传入NodeConfig,用于加载/保存密钥(如KMS,HSM). - 纯文本文件( 不推荐) - 阅读/写作
identity.key内dataDir(单位:千美元)~/.antseed/默认)0600权限。 由于此密钥也是您的链上钱包, 因此在制作时避免在磁盘上存储未加密的钱包 .
如果没有找到身份,则通过活性商店生成出新的键盘并持续使用.
文件存储( 默认)
import { AntseedNode, FileIdentityStore } from '@antseed/node';
const node = new AntseedNode({
role: 'seller',
// These are equivalent — FileIdentityStore is the default:
identityStore: new FileIdentityStore('/path/to/config-dir'),
// dataDir: '/path/to/config-dir',
});
环境变量
从密钥管理器( AWS SSM, HashiCorp Vault等) 中传出私钥六进制 :
export ANTSEED_IDENTITY_HEX="$(vault kv get -field=key secret/antseed/identity)"
antseed seller start
该变量在消费后立即从工艺环境中清除出.
自定义存储
执行 IdentityStore 任何后端的接口 :
import { AntseedNode, type IdentityStore } from '@antseed/node';
class VaultIdentityStore implements IdentityStore {
async load(): Promise<string | null> {
// Read 64-char hex string from your backend
return await vault.getSecret('antseed-identity');
}
async save(hexKey: string): Promise<void> {
// Persist the 64-char hex string
await vault.putSecret('antseed-identity', hexKey);
}
}
const node = new AntseedNode({
role: 'seller',
identityStore: new VaultIdentityStore(),
});
桌面应用程序
蚂蚁种子桌面应用程序在休息时使用 Electron 加密身份 safeStorage API (英语). 加密密钥存储在OS密钥链(macOS Keychain / Windows DPAPI / Linux libsecret)中,加密的blob存储于 ~/.antseed/identity.enc。在第一次发射时,任何已有的简写 identity.key 已迁移到加密商店并被删除.
现成定居流动
何时 payments.enabled=true 在销售模式中 :
- 通过
BuyerPaymentManager。 。 。 . - 存款余额在会话开始时锁定在链上.
- 在处理请求时生成使用费收据.
- 关于闲置/会期定稿,
calculateSettlement从收据中计算费用,并通过下列方式结算:ChannelsClient.settle(sessionId, tokenCount)
- 任何未使用的预留款都根据同一结算交易的合同逻辑退还买方.
最小加密配置 :
const node = new AntseedNode({
role: 'seller',
payments: {
enabled: true,
paymentMethod: 'crypto',
defaultSessionAmountUSDC: '1',
sellerWalletAddress: '0xSeller...',
paymentConfig: {
crypto: {
chainId: 'base',
rpcUrl: process.env.RPC_URL!,
depositsContractAddress: process.env.DEPOSITS_ADDRESS!,
channelsContractAddress: process.env.CHANNELS_ADDRESS!,
usdcContractAddress: process.env.USDC_ADDRESS!,
autoFundDeposit: true,
},
},
},
});
智能合同来源和部署说明: node/contracts/README.md。 。 。 .
密钥导出
承认使用费帮助者
从 @antseed/node/payments数字 :
SellerRegistryClient.getRegisteredAgentId(seller)明确返回 绑定身份,或0当仅存在后遗症时.registerSellerBinding(signer, agentId, onConfirmed?)结实而加以证实, 返回时false已绑定时没有交易。 可选 回调在核查前收到确认的散列; 核查 失败抛出SellerRegistrationVerificationError。 。 。 .SellerPoolsClient.allStakerPositionIds(seller)活性位置;rewardPositions(seller)还发现了从燃烧日志中取出的位置. 历史发现需要一个具有历史代码和日志访问权限的RPC.earlyExitSlashBps(id)财务报告和审定财务报表estimateEarlyExit(position, slashBps)提供 a 估计数,而不是交易执行时的保证最大损失.SellerPoolsRewardsClient.previewStakerRewards(positionIds)返回ANTS 按输入顺序排列的基准单位金额,包括未索引的已完成的时代. 每次呼叫都使用自己的单块快照并读取缓存; 重复使用 a 客户端不保存 stale 预览 .previewStakerReward(id)这是 单位等同. 两种方法都不发送交易.previewPoolRewards, (中文(简体) ),pendingEpochRewards, (中文(简体) ),claimPoolRewards, (中文(简体) ),claimEpochRewards,以及claimBuyerEpochRewards提供共同的发现, 预览 和 限定的 主张 管弦 。 池索偿指数 在声称之前。 回调显示没有CLI输出的确认交易.ANTSTokenClient.receivedInTransaction(hash, recipient)收到的ANTS金额 从成功的交易收据中转帐,而不是使用估计数 与索赔总额相同.
核心 API
// Main class
import { AntseedNode, type NodeConfig } from '@antseed/node';
// Interfaces
import type { Provider } from '@antseed/node';
import type { Router } from '@antseed/node';
import type {
AntseedPlugin,
AntseedProviderPlugin,
AntseedRouterPlugin,
ConfigField,
} from '@antseed/node';
// Identity & P2P
import { loadOrCreateIdentity, type Identity, type IdentityStore, FileIdentityStore } from '@antseed/node';
import { NatTraversal, type NatMapping, type NatTraversalResult } from '@antseed/node';
// Discovery
import { DHTNode, DEFAULT_DHT_CONFIG } from '@antseed/node';
import { OFFICIAL_BOOTSTRAP_NODES, mergeBootstrapNodes, toBootstrapConfig } from '@antseed/node';
import { MetadataServer, type MetadataServerConfig } from '@antseed/node';
import type { PeerMetadata, ProviderAnnouncement } from '@antseed/node';
// Metering & Payments
import { MeteringStorage } from '@antseed/node';
import { BalanceManager } from '@antseed/node';
import { BuyerPaymentManager, calculateSettlement } from '@antseed/node/payments';
import { BaseChannelsClient } from '@antseed/node';
// Routing & Proxy
import { ProxyMux } from '@antseed/node';
import { DefaultRouter, type DefaultRouterConfig } from '@antseed/node';
import { resolveProvider } from '@antseed/node';
// Plugin system
import { loadPluginModule, loadAllPlugins } from '@antseed/node';
import type { ConfigField } from '@antseed/node';
还提供次级模块进口:
import { DHTNode } from '@antseed/node/discovery';
import { MeteringStorage } from '@antseed/node/metering';
import { BalanceManager } from '@antseed/node/payments';
提供者接口
执行 Provider 将 LLM 后端曝光为网络上的提供者.
interface Provider {
/** Unique name for this provider (e.g., 'anthropic', 'openai') */
name: string;
/** Model IDs this provider supports */
services: string[];
/** Pricing in USD per 1M tokens (defaults + optional per-service overrides) */
pricing: {
defaults: { inputUsdPerMillion: number; cachedInputUsdPerMillion?: number; outputUsdPerMillion: number };
services?: Record<string, { inputUsdPerMillion: number; cachedInputUsdPerMillion?: number; outputUsdPerMillion: number }>;
};
/** Optional per-service discovery tags (e.g., coding/privacy/legal) */
serviceCategories?: Record<string, string[]>;
/** Optional per-service API protocol support advertised via discovery metadata. */
serviceApiProtocols?: Record<string, ServiceApiProtocol[]>;
/** Maximum concurrent requests this provider can handle */
maxConcurrency: number;
/** Handle an incoming inference request and return the response */
handleRequest(req: SerializedHttpRequest): Promise<SerializedHttpResponse>;
/** Return current and maximum concurrent request counts */
getCapacity(): { current: number; max: number };
/** Optional startup hook (credential validation, warm-up, etc.) */
init?(): Promise<void>;
/** Optional capabilities beyond plain inference */
capabilities?: ProviderCapability[];
}
路由器接口
执行 Router 以控制买方如何选择将每项请求引向哪个卖方.
interface Router {
/** Pick the best peer for a given request from the available peers. Return null to reject. */
selectPeer(req: SerializedHttpRequest, peers: PeerInfo[]): PeerInfo | null;
/** Called after each request completes so the router can update internal state. */
onResult(peer: PeerInfo, result: {
success: boolean;
latencyMs: number;
tokens: number;
}): void;
}
如果没有设置路由器, SDK 使用内置 DefaultRouter 选择最低声誉阈值以上最便宜的对等者。 CLI 买主代理在发送前添加了特定模式的规划层: 光亮的模型代号被卡通化并按 @antseed/node/model-routing 使用共享价格+信托优惠,健康信号,以及卖方准入规则. 明确的对等针绕过自动对等选择.
构建自定义提供者插件
提供者插件包成一个 Provider 因此可以通过CLI安装并配置.
import type { AntseedProviderPlugin, Provider, SerializedHttpRequest, SerializedHttpResponse } from '@antseed/node';
class MyProvider implements Provider {
readonly name = 'my-provider';
readonly services: string[];
readonly pricing: Provider['pricing'];
readonly maxConcurrency: number;
private _active = 0;
constructor(apiKey: string, services: string[], inputUsdPerMillion: number, outputUsdPerMillion: number, maxConcurrency: number) {
this.services = services;
this.pricing = {
defaults: {
inputUsdPerMillion,
cachedInputUsdPerMillion: inputUsdPerMillion * 0.1, // optional, defaults to inputUsdPerMillion
outputUsdPerMillion,
},
};
this.maxConcurrency = maxConcurrency;
}
async handleRequest(req: SerializedHttpRequest): Promise<SerializedHttpResponse> {
this._active++;
try {
// Forward req to your upstream LLM and return the response
const upstream = await fetch('https://my-llm.example.com/v1/chat', {
method: req.method,
headers: req.headers,
body: req.body,
});
return {
requestId: req.requestId,
statusCode: upstream.status,
headers: Object.fromEntries(upstream.headers.entries()),
body: new Uint8Array(await upstream.arrayBuffer()),
};
} finally {
this._active--;
}
}
getCapacity() {
return { current: this._active, max: this.maxConcurrency };
}
}
const plugin: AntseedProviderPlugin = {
name: 'my-provider',
displayName: 'My Provider',
version: '1.0.0',
type: 'provider',
description: 'Provides My LLM capacity on the Antseed Network',
configSchema: [
{ key: 'MY_API_KEY', label: 'API Key', type: 'secret', required: true, description: 'API key for My LLM' },
{ key: 'MY_SERVICES', label: 'Services', type: 'string[]', required: false, description: 'Comma-separated service list' },
{ key: 'MY_INPUT_USD_PER_MILLION', label: 'Input Price', type: 'number', required: false, description: 'Input price in USD per 1M tokens' },
{ key: 'MY_OUTPUT_USD_PER_MILLION', label: 'Output Price', type: 'number', required: false, description: 'Output price in USD per 1M tokens' },
],
createProvider(config: Record<string, string>) {
const apiKey = config['MY_API_KEY'] ?? '';
const services = (config['MY_SERVICES'] ?? 'default-service').split(',').map(s => s.trim());
const input = parseFloat(config['MY_INPUT_USD_PER_MILLION'] ?? '10');
const output = parseFloat(config['MY_OUTPUT_USD_PER_MILLION'] ?? String(input));
return new MyProvider(apiKey, services, input, output, 10);
},
};
export default plugin;
构建自定义路由器插件
路由器插件包 Router 用于基于CLI的安装和配置.
import type { AntseedRouterPlugin, Router, PeerInfo, SerializedHttpRequest } from '@antseed/node';
class CheapestRouter implements Router {
private readonly _maxInputUsdPerMillion: number;
constructor(maxInputUsdPerMillion: number) {
this._maxInputUsdPerMillion = maxInputUsdPerMillion;
}
selectPeer(_req: SerializedHttpRequest, peers: PeerInfo[]): PeerInfo | null {
const eligible = peers
.filter(p => (p.defaultInputUsdPerMillion ?? Infinity) <= this._maxInputUsdPerMillion)
.sort((a, b) => (a.defaultInputUsdPerMillion ?? 0) - (b.defaultInputUsdPerMillion ?? 0));
return eligible[0] ?? null;
}
onResult(_peer: PeerInfo, _result: { success: boolean; latencyMs: number; tokens: number }): void {
// Track metrics, update reputation, etc.
}
}
const plugin: AntseedRouterPlugin = {
name: 'cheapest',
displayName: 'Cheapest Router',
version: '1.0.0',
type: 'router',
description: 'Always routes to the cheapest available peer',
configSchema: [
{ key: 'MAX_INPUT_USD_PER_MILLION', label: 'Max Input Price', type: 'number', required: false, description: 'Maximum input price in USD per 1M tokens' },
],
createRouter(config: Record<string, string>) {
const maxInput = parseFloat(config['MAX_INPUT_USD_PER_MILLION'] ?? 'Infinity');
return new CheapestRouter(maxInput);
},
};
export default plugin;
插件生态系统
Antseed插件系统使用简单的合同:
- 提供者插件 (单位:千美元)
AntseedProviderPlugin)导出默认对象type: 'provider'(单位:千美元)createProvider(config)工厂. - 路由器插件 (单位:千美元)
AntseedRouterPlugin)导出默认对象type: 'router'(单位:千美元)createRouter(config)工厂. - 两种插件类型都通过
configSchema,以ConfigField对象 :
interface ConfigField {
key: string; // Environment variable name
label: string; // Human-readable label
type: 'string' | 'number' | 'boolean' | 'secret' | 'string[]';
required?: boolean; // Whether the key must be set
default?: unknown; // Default value
description?: string; // Description shown in CLI
}
CLI从环境变量中读取这些密钥,然后通过它们作为 Record<string, string> 到工厂的功能。 插件安装于 antseed plugin add <package-name>。 。 。 .