signet
你的 AI 代理刚刚调用了一个工具。你能证明它做了什么吗?
大多数代理栈在事后记录操作,但从不验证实际发送的内容。如果请求被重放、篡改或伪造,执行端将无法知晓。
Signet 解决了这个问题:每个代理都获得一个 Ed25519 身份,每个工具调用都被签名,一个哈希链审计日志记录了发生的一切,客户端或服务器可以在信任请求之前对其进行验证。3 行代码签名。3 行代码验证。开源。
如果 Signet 对你有帮助,请给此仓库加星以帮助更多团队发现它。
从下面的 CLI 流程开始查看签名操作,然后跳转到查看它拒绝错误请求,观察服务器在未签名、被篡改、过时或目标错误的请求运行之前将其拦截。
为什么选择 Signet
Signet 为代理操作添加了一个轻量级的信任层:
签名:使用代理的加密密钥对每个工具调用进行签名
审计:使用仅追加的哈希链本地日志记录发生的一切
验证:离线验证任何操作收据,无需网络
集成:与 Claude Code、Codex CLI、MCP 客户端和服务器、Python 框架以及 Vercel AI SDK 集成
30 秒内试用
pip install signet-authfrom signet_auth import SigningAgent
agent = SigningAgent.create("my-agent", owner="team")
receipt = agent.sign("github_create_issue", params={"title": "fix bug"})
assert agent.verify(receipt)
print(receipt.id)如果你是新手,请从以下四条路径之一开始:
选择你的路径
Claude Code:最适合在编码代理中进行最快的首次运行。在 Claude Code 中运行
/plugin install signet@claude-plugins-official。5 分钟内,你将拥有已签名的工具调用和位于~/.signet/audit/的本地审计日志。Codex CLI:最适合在 Codex 中签署 Bash 工具调用。将
plugins/codex/复制到~/.codex/plugins/signet并添加一个PostToolUse钩子。5 分钟内,你将使用相同的审计跟踪在 Codex 中拥有已签名的 Bash 操作。MCP 客户端:如果你控制 MCP 客户端或传输,这是最佳选择。使用
new SigningTransport(inner, secretKey, "my-agent")包装你的传输。5 分钟内,你将拥有已签名的tools/call请求,并在params._meta._signet中包含收据。MCP 服务器:如果你想在执行前进行验证,这是最佳选择。在你的工具处理程序中调用
verifyRequest(request, {...})。5 分钟内,你将在执行边界拥有签名者、新鲜度、目标绑定以及工具/参数检查。
查看它拒绝错误请求
运行最短的执行边界演示:
cd examples/mcp-agent
npm run execution-boundary-demo查看 examples/mcp-agent/demo-execution-boundary.mjs 获取演示源码。
团队何时需要 Signet
你需要为编码代理、MCP 工具或 CI 自动化提供审计跟踪
你需要在事件发生后证明是哪个代理请求了操作
你需要无需依赖托管服务即可离线验证的收据
你想要已签名的工具调用证据,而无需在你的栈中添加代理或网关
Signet 是什么,不是什么
Signet 是代理操作的证明层:签名、审计和验证
Signet 旨在通过 SDK、插件和 MCP 中间件融入现有的代理栈
Signet 不是策略引擎、防火墙或操作拦截器
Signet 不是网关的替代品;它是预防和执行工具的补充
安装
# CLI
cargo install signet-cli
# Python
pip install signet-auth
# TypeScript (MCP middleware)
npm install @signet-auth/core @signet-auth/mcp
# TypeScript (MCP server verification)
npm install @signet-auth/mcp-server
# TypeScript (Vercel AI SDK middleware)
npm install @signet-auth/vercel-ai快速入门
Claude Code 插件
在 Claude Code 中自动签署每个工具调用,无需配置:
# Option A: From the official Anthropic plugin marketplace
/plugin install signet@claude-plugins-official
# Option B: Add Signet as a marketplace source, then install
/plugin marketplace add Prismer-AI/signet
/plugin install signet@signet每个工具调用都使用 Ed25519 签名,并记录到 ~/.signet/audit/ 的哈希链审计跟踪中。
其他安装方法:
# From Git
claude plugin add --from https://github.com/Prismer-AI/signet
# Via signet CLI
signet claude installCodex 插件
在 Codex CLI 中自动签署每个 Bash 工具调用:
git clone https://github.com/Prismer-AI/signet.git
cp -r signet/plugins/codex ~/.codex/plugins/signet然后将钩子添加到 ~/.codex/hooks.json:
{
"hooks": {
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "node \"$HOME/.codex/plugins/signet/bin/sign.cjs\"",
"timeout": 5
}]
}]
}
}或者使用 MCP 服务器进行按需签名工具:
codex mcp add signet -- npx @signet-auth/mcp-toolsCLI
# Generate an agent identity
signet identity generate --name my-agent
# Sign an action
signet sign --key my-agent --tool "github_create_issue" \
--params '{"title":"fix bug"}' --target mcp://github.local
# Verify a receipt
signet verify receipt.json --pubkey my-agent
# Audit recent actions
signet audit --since 24h
# Verify log integrity
signet verify --chainMCP 客户端集成 (TypeScript)
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { generateKeypair } from "@signet-auth/core";
import { SigningTransport } from "@signet-auth/mcp";
// Generate an agent identity
const { secretKey } = generateKeypair();
// Wrap any MCP transport -- all tool calls are now signed
const inner = new StdioClientTransport({ command: "my-mcp-server" });
const transport = new SigningTransport(inner, secretKey, "my-agent");
const client = new Client({ name: "my-agent", version: "1.0" }, {});
await client.connect(transport);
// Every callTool() is now cryptographically signed
const result = await client.callTool({
name: "echo",
arguments: { message: "Hello!" },
});每个 tools/call 请求都会将已签名的收据注入到 params._meta._signet 中。
MCP 服务器验证
如果你也控制 MCP 服务器,请在执行前验证请求:
import { verifyRequest } from "@signet-auth/mcp-server";
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const verified = verifyRequest(request, {
trustedKeys: ["ed25519:..."],
maxAge: 300,
});
if (!verified.ok) return { content: [{ type: "text", text: verified.error }], isError: true };
console.log(`Verified: ${verified.signerName}`);
// process tool call...
});Vercel AI SDK 集成
import { generateText } from "ai";
import { generateKeypair } from "@signet-auth/core";
import { createSignetCallbacks } from "@signet-auth/vercel-ai";
const { secretKey } = generateKeypair();
const callbacks = createSignetCallbacks(secretKey, "my-agent");
const result = await generateText({
model: openai("gpt-4"),
tools: { myTool },
...callbacks,
prompt: "...",
});
// Every tool call is now signed
console.log(callbacks.receipts);参考 MCP 服务器
此仓库还包含一个最小的 MCP 参考服务器,演示了使用 @signet-auth/mcp-server 进行服务器端验证。
cd examples/mcp-agent
npm ci
npm run verifier-server可用工具:
inspect_current_request— 如果当前 MCP 工具调用包含params._meta._signet,则验证该调用verify_receipt— 根据公钥验证原始 Signet 收据verify_request_payload— 离线验证合成的 MCPtools/call有效负载
环境变量:
SIGNET_TRUSTED_KEYS— 以逗号分隔的ed25519:<base64>公钥SIGNET_REQUIRE_SIGNATURE—true或false(默认false)SIGNET_MAX_AGE— 收据最大有效期(秒,默认300)SIGNET_EXPECTED_TARGET— 可选的预期receipt.action.target
独立 MCP 签名服务器
@signet-auth/mcp-tools 将 Signet 签名、验证和内容哈希作为 MCP 工具公开 — 插入任何兼容 MCP 的客户端:
npx @signet-auth/mcp-tools可用工具:signet_generate_keypair, signet_sign, signet_verify, signet_content_hash。
Python (LangChain / CrewAI / AutoGen + 6 更多)
pip install signet-authfrom signet_auth import SigningAgent
# Create an agent identity (saved to ~/.signet/keys/)
agent = SigningAgent.create("my-agent", owner="willamhou")
# Sign any tool call -- receipt is auto-appended to audit log
receipt = agent.sign("github_create_issue", params={"title": "fix bug"})
# Verify
assert agent.verify(receipt)
# Query audit log
for record in agent.audit_query(since="24h"):
print(f"{record.receipt.ts} {record.receipt.action.tool}")LangChain 集成
from signet_auth import SigningAgent
from signet_auth.langchain import SignetCallbackHandler
agent = SigningAgent("my-agent")
handler = SignetCallbackHandler(agent)
# Every tool call is now signed + audited
chain.invoke(input, config={"callbacks": [handler]})
# Async chains supported too
from signet_auth.langchain import AsyncSignetCallbackHandlerCrewAI 集成
from signet_auth import SigningAgent
from signet_auth.crewai import install_hooks
agent = SigningAgent("my-agent")
install_hooks(agent)
# All CrewAI tool calls are now globally signed
crew.kickoff()AutoGen 集成
from signet_auth import SigningAgent
from signet_auth.autogen import signed_tool, sign_tools
agent = SigningAgent("my-agent")
# Wrap a single tool
wrapped = signed_tool(tool, agent)
# Or wrap all tools at once
wrapped_tools = sign_tools([tool1, tool2], agent)LangGraph 集成
LangGraph 使用 LangChain 的回调系统 — 相同的处理程序可以直接工作:
from signet_auth import SigningAgent
from signet_auth.langgraph import SignetCallbackHandler
agent = SigningAgent("my-agent")
handler = SignetCallbackHandler(agent)
result = graph.invoke(input, config={"callbacks": [handler]})LlamaIndex 集成
from signet_auth import SigningAgent
from signet_auth.llamaindex import install_handler
agent = SigningAgent("my-agent")
handler = install_handler(agent)
# All tool call events are now signed
index = ... # your LlamaIndex setup
response = index.as_query_engine().query("What is Signet?")
# Access receipts
print(handler.receipts)Pydantic AI 集成
from signet_auth import SigningAgent
from signet_auth.pydantic_ai_integration import SignetMiddleware
agent = SigningAgent("my-agent")
middleware = SignetMiddleware(agent)
@middleware.wrap
def my_tool(query: str) -> str:
return f"result: {query}"Google ADK 集成
from signet_auth import SigningAgent
from signet_auth.google_adk import SignetPlugin
agent = SigningAgent("my-agent")
plugin = SignetPlugin(agent)
# Pass as callback to ADK agentSmolagents 集成
from signet_auth import SigningAgent
from signet_auth.smolagents import signet_step_callback
agent = SigningAgent("my-agent")
callback = signet_step_callback(agent)
bot = CodeAgent(tools=[...], model=model, step_callbacks=[callback])OpenAI Agents SDK 集成
from signet_auth import SigningAgent
from signet_auth.openai_agents import SignetAgentHooks
agent = SigningAgent("my-agent")
oai_agent = Agent(
name="assistant",
hooks=SignetAgentHooks(agent),
tools=[...],
)注意: 工具调用参数在钩子 API 中尚不可用(issue #939)。仅签署工具名称。
低级 API
from signet_auth import generate_keypair, sign, verify, Action
kp = generate_keypair()
action = Action("github_create_issue", params={"title": "fix bug"})
receipt = sign(kp.secret_key, action, "my-agent", "willamhou")
assert verify(receipt, kp.public_key)双边收据(服务器共同签名)
from signet_auth import generate_keypair, sign, sign_bilateral, verify_bilateral, Action
# Agent signs the tool call
agent_kp = generate_keypair()
action = Action("github_create_issue", params={"title": "fix bug"})
agent_receipt = sign(agent_kp.secret_key, action, "my-agent")
# Server co-signs with the response
server_kp = generate_keypair()
bilateral = sign_bilateral(
server_kp.secret_key, agent_receipt,
{"content": [{"type": "text", "text": "issue #42 created"}]},
"github-server",
)
assert verify_bilateral(bilateral, server_kp.public_key)
assert bilateral.v == 3 # v3 = bilateral receipt工作原理
Your Agent
|
v
SigningTransport (wraps any MCP transport)
|
+---> Signs each tool call (Ed25519)
+---> Appends Action Receipt to local audit log (hash-chained)
+---> Forwards request to MCP server (unchanged)仅代理端。MCP 服务器无需更改。
操作收据
每个工具调用都会产生一个已签名的收据:
{
"v": 1,
"id": "rec_e7039e7e7714e84f...",
"action": {
"tool": "github_create_issue",
"params": {"title": "fix bug"},
"params_hash": "sha256:b878192252cb...",
"target": "mcp://github.local",
"transport": "stdio"
},
"signer": {
"pubkey": "ed25519:0CRkURt/tc6r...",
"name": "demo-bot",
"owner": "willamhou"
},
"ts": "2026-03-29T23:24:03.309Z",
"nonce": "rnd_dcd4e135799393...",
"sig": "ed25519:6KUohbnSmehP..."
}签名涵盖整个收据主体(操作 + 签名者 + 时间戳 + 随机数),使用 RFC 8785 (JCS) 规范 JSON。修改任何字段都会使签名失效。
CLI 命令
命令 | 描述 |
| 生成 Ed25519 身份(默认加密) |
| 生成不加密的身份(用于 CI) |
| 列出所有身份 |
| 将公钥导出为 JSON |
| 签署操作 |
| 仅存储参数哈希(非原始参数) |
| 将收据写入文件而不是 stdout |
| 跳过审计日志追加 |
| 验证收据签名 |
| 验证审计日志哈希链完整性 |
| 列出最近的操作 |
| 按时间过滤(例如 24h, 7d) |
| 按工具名称过滤 |
| 验证所有收据签名 |
| 将记录导出为 JSON |
| 安装 Claude Code 插件 (PostToolUse 签名钩子) |
| 卸载 Claude Code 插件 |
通过交互式提示或 SIGNET_PASSPHRASE 环境变量(用于 CI)传递密码。
文档
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Prismer-AI/signet'
If you have feedback or need assistance with the MCP directory API, please join our Discord server