Signet

by prismer-ai

Not rated
GitHub

About

Cryptographic action receipts for AI agents. Signs every MCP tool call with Ed25519, hash-chained audit log. 3 lines of code to integrate.

Details

Author
prismer-ai
Categories
Developer Tools, Security, AI

Setup

Install Signet in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/prismer-ai/signet

Follow the installation instructions in the repository README, then restart your MCP client.

Don't just log agent actions. Prove them.
Cryptographic receipts for every AI agent tool call — signed, hash-chained, offline-verifiable. Independent of any provider.

TypeScript packages:@signet-auth/core·@signet-auth/mcp·@signet-auth/mcp-server·@signet-auth/mcp-tools·@signet-auth/node·@signet-auth/vercel-ai

▶ Try the live demo— sign a tool call in your browser, change a field, and watch verification fail.(mirror:GitHub Pages)

▶ Walkthrough: signing, audit log, and verification·▶ Demo: execution boundary & MCP integration

Single-host pilot flow: sign every tool call, hand off a signed evidence bundle, re-verify on any machine — no signet keystore required.Pilot runbook →

Your AI agent just placed an order, deleted a row, sent an email, merged a PR. Can you prove exactly what it did — to an auditor, a customer, or yourself after an incident?

Signet is theindependent verification layerfor agent actions. Every tool call gets a signed receipt that anyone can verify offline, without trusting the platform that hosted the agent or the vendor that stored the logs.

Your agents run on their infrastructure. The proof belongs to you.

Traditional logs tell you what a platformsayshappened. They're mutable, provider-dependent, and unverifiable without trusting the party that wrote them.

Signet receipts are different. Modify any field — tool name, parameters, timestamp, signer — and the Ed25519 signature breaks. Delete or reorder entries and the SHA-256 hash chain breaks. Verification requires only the public key. No network call, no API, no login.

Use logs for observability. Use Signet when you needevidence.

- MCP builders— wrap any MCP server withsignet proxy, sign everytools/call, no code changes
- Security / compliance teams— tamper-evident audit trail that satisfies EU AI Act Art. 12, SOC 2 CC7.2, ISO 27001 A.8.15
- Enterprise agent platforms— prove what the agent did, who authorized it, which policy was in force
- Framework users— LangChain, CrewAI, Claude Code, Codex, OpenAI Agents, Vercel AI SDK — all supported
- Agent-to-agent deployments— bilateral co-signing when both sides hold keys

If a tool call cannot be verified independently, it should not be trusted unconditionally.This matters when an auditor asks for proof, when an incident happens on infrastructure you don't control, or when the question isn't "what does the console say" but "what actually happened."

Each agent gets an Ed25519 identity. Every tool call can be signed, appended to a hash-chained audit trail, verified offline or before execution, co-signed by the server, bound to a delegation chain, and optionally bound to a policy decision.

The video above shows the full flow. The SVG below shows the CLI signing details, or jump toSee It Reject Bad Requeststo watch the server block bad requests before they run.

This first demo shows signing + audit receipts. See also theMCP flow diagram.

Signet adds a lightweight trust layer for agent actions:

- Signevery tool call with the agent's cryptographic key
- Verifyrequests offline or at the execution boundary before they are trusted
- Proxyany MCP server transparently — sign requests without touching agent or server code, with local bilateral audit co-signing in the proxy path
- Co-signserver responses with bilateral receipts when you control both sides
- Tracemulti-step workflows by linking receipts withtrace_idandparent_receipt_id
- Authorizeagents with scoped delegation chains that prove who allowed the action
- Attest policyby embedding a signedPolicyAttestationwhen a YAML policy is satisfied
- Inspect locallywith an append-only audit log and dashboard, no hosted control plane required

- MCP proxy:signet proxy --target <cmd> --key <name>— drop Signet in front of any MCP server as a transparent stdio proxy. No changes to the agent or server required. Signs everytools/calland appends bilateral co-signatures to the local audit path; client-visible bilateral response handling is stronger through integrated transport/server helpers.
- Trace correlation:trace_idandparent_receipt_idfields onActionlink receipts across multi-step workflows into a causal chain. Both fields are part of the signed payload — tampering invalidates the signature.
- Policy engine:signet sign --policy policy.yamlenforces policy before signing and binds the decision into the receipt. The proxy also respects--policy, blocking denied calls before they reach the server while producing signed bilateralrejected/requires_approvaloutcomes and a hash-chainedpolicy_violationaudit record.
- Delegation chains:signet delegate ...produces v4 receipts that prove who authorized the agent and what scope it had.
- Local dashboard:signet dashboardshows timeline, chain integrity, signature health, and delegated vs direct activity.
- Broader integrations: official Claude Code plugin, Codex plugin, MCP middleware, Python SDK, and Vercel AI SDK callbacks.

Signet provides the technical controls that auditors look for when assessing AI agent operations. See the fullCompliance Mappingfor details.

Signet is a tool, not a certification. It provides controls that support compliance — your deployment and configuration determine compliance posture.

from 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)

Signet is building a new category:verifiable tool-call receipts for AI agents. Starring isn't just a bookmark — it helps push cryptographic evidence for agent actions into the ecosystem so regulated industries, enterprise platforms, and framework users don't have to roll their own.

- Working withMicrosoft Agent Governance Toolkit(example merged inPR #1196)
- Named contributor inLangChain's ComplianceBackend RFC(
#35691)
- Conformance work toward theIETF draft-farley-acta-signed-receiptsspec
- Maps toNIST NCCoE's four pillarsfor AI agent identity and authorization (Q4 2026 Interoperability Profile)

If you're building agents that need to survive an audit, an incident, or a third party asking "prove it" — star the repo, try it, open an issue.

If you're new, start with one of these five paths:

- Claude Code: Best for the fastest first run in a coding agent. Run/plugin install signet@claude-plugins-officialin Claude Code. In 5 minutes you'll have signed tool calls and a local audit log at~/.signet/audit/.
-
Codex CLI: Best for signing Bash tool calls in Codex. Copyplugins/codex/into~/.codex/plugins/signetand add onePostToolUsehook. In 5 minutes you'll have signed Bash actions in Codex using the same audit trail.
-
Python SDK: Best if you want receipts inside LangGraph, LlamaIndex, OpenAI Agents, CrewAI, or your own tool runner. Start withSigningAgent.create(...)and add framework hooks only where you need them.
-
MCP clients: Best if you control an MCP client or transport. Wrap your transport withnew SigningTransport(inner, secretKey, "my-agent"). In 5 minutes you'll have signedtools/callrequests with receipts inparams._meta._signet.
-
MCP servers: Best if you want verification before execution. CallverifyRequest(request, {...})in your tool handler. In 5 minutes you'll have signer, freshness, target-binding, and tool/params checks at the execution boundary.

Run the shortest execution-boundary demo:

cd examples/mcp-agent npm run execution-boundary-demo

Prefer motion? Download theMP4orGIF.

Seeexamples/mcp-agent/demo-execution-boundary.mjsfor the demo source.

Delegation Chains: Who Authorized This Agent?

Signet receipts provewhathappened. Delegation chains provewho allowed it.

A root identity (human or org) cryptographically delegates scoped authority to an agent. Permissions can only narrow, never widen. The agent's v4 receipt carries the full proof of authorization.

Owner (alice) → Agent A (tools: [Bash, Read], max_depth: 0) ↓ v4 Receipt: tool=Bash, authorization.chain proves alice → Agent A
# Create a delegation token (expires in 24 hours) signet delegate create --from alice --to deploy-bot --to-name deploy-bot \ --tools Bash,Read --targets "mcp://github" --max-depth 0 --ttl 24h # Sign with authorization proof (v4 receipt) signet delegate sign --key deploy-bot --tool Bash \ --params '{"cmd":"git pull"}' --target "mcp://github" --chain chain.json # Verify: signature + chain + scope + root trust signet delegate verify-auth receipt.json --trusted-roots alice

Best practice:Use short-lived delegations (--ttl 1h,--ttl 24h) instead of long-lived or non-expiring tokens. If an agent is compromised, the delegation expires automatically. Re-issue tokens as needed. This is the same pattern used by short-lived JWTs and X.509 certificates.

from signet_auth import sign_delegation, sign_authorized, verify_authorized # Delegation functions accept JSON strings for scope, chain, and receipts token_json = sign_delegation(root_key_b64, "alice", agent_pubkey_b64, "bot", scope_json) receipt_json = sign_authorized(agent_key_b64, action_json, "bot", f"[{token_json}]") scope_json = verify_authorized(receipt_json, [root_pubkey_b64])

Signet can enforce a YAML policy before signing. When an action is allowed, the signed receipt carries aPolicyAttestationproving which policy hash, rule, and decision were in force.

version: 1 name: production-agents default_action: deny rules: - id: allow-read match: tool: Read action: allow - id: deny-rm-rf match: tool: Bash params: command: contains: "rm -rf" action: deny reason: destructive command
signet policy validate policy.yaml signet policy check policy.yaml --tool Bash --params '{"command":"rm -rf /"}' signet sign --key deploy-bot --tool Read \ --params '{"path":"README.md"}' --target "mcp://github" --policy policy.yaml

Denied actions fail before a receipt is produced. Allowed actions produce a receipt whose signed payload proves the policy decision.

- You need a tamper-evident audit trail for coding agents, MCP tools, or CI automation
- You want to prove which agent requested an action and who authorized it after an incident
- You need receipts that can be verified offline without depending on a hosted service
- You want lightweight policy enforcement before signing without adding a proxy to your stack

- Signet isa trust layer for agent actions: signing, audit, verification, delegation, and policy attestation
- Signet isdesigned to fit into existing agent stacks with SDKs, plugins, and MCP middleware
- Signet canreject unsigned, stale, replayed, or mis-targeted MCP requests before execution
- Signet candeny actions before signing when you provide a policy file
- Signet is nota hosted gateway, always-on control plane, or replacement for sandboxing and least-privilege design

# 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 (Node local audit/operator helpers) npm install @signet-auth/node # TypeScript (Vercel AI SDK middleware) npm install @signet-auth/vercel-ai # TypeScript (standalone MCP signing server) npx @signet-auth/mcp-tools

Auto-sign every tool call inClaude Codewith zero configuration:

# 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

Every tool call is signed with Ed25519 and logged to a hash-chained audit trail at~/.signet/audit/.

# From Git claude plugin add --from https://github.com/Prismer-AI/signet # Via signet CLI signet claude install

Auto-sign every Bash tool call inCodex CLI:

git clone https://github.com/Prismer-AI/signet.git cp -r signet/plugins/codex ~/.codex/plugins/signet

Then add the hook to~/.codex/hooks.json:

{ "hooks": { "PostToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "node \"$HOME/.codex/plugins/signet/bin/sign.cjs\"", "timeout": 5 }] }] } }

Or use the MCP server for on-demand signing tools:

codex mcp add signet -- npx @signet-auth/mcp-tools
# 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 --chain
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!" }, });

Everytools/callrequest gets a signed receipt injected intoparams._meta._signet.

If you control the MCP server too, verify requests before execution:

import { FileNonceCache, verifyRequest } from "@signet-auth/mcp-server"; const nonceCache = new FileNonceCache(".signet/nonces.json"); server.setRequestHandler(CallToolRequestSchema, async (request) => { const verified = verifyRequest(request, { trustedKeys: ["ed25519:..."], maxAge: 300, nonceCache, }); if (!verified.ok) return { content: [{ type: "text", text: verified.error }], isError: true }; if (!verified.trusted) return { content: [{ type: "text", text: "untrusted signer" }], isError: true }; console.log(Verified: ${verified.signerName}); // process tool call... });
import { generateText } from "ai"; import { openai } from "@ai-sdk/openai"; 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-4o"), tools: { myTool }, ...callbacks, prompt: "...", }); // Every tool call is now signed console.log(callbacks.receipts);

This repo also includes a minimal MCP reference server that demonstrates server-side verification with@signet-auth/mcp-server.

cd examples/mcp-agent npm ci npm run verifier-server

- inspect_current_request— verifies the current MCP tool call if it includesparams._meta._signet
- verify_receipt— verifies a raw Signet receipt against a public key
- verify_request_payload— verifies a synthetic MCPtools/callpayload offline

- SIGNET_TRUSTED_KEYS— comma-separateded25519:<base64>public keys
- SIGNET_REQUIRE_SIGNATUREtrueorfalse(defaulttrue)
- SIGNET_REQUIRE_TRUSTED_SIGNERtrueorfalse(defaulttrue)
- SIGNET_MAX_AGE— max receipt age in seconds (default300)
- SIGNET_EXPECTED_TARGET— optional expectedreceipt.action.target

@signet-auth/mcp-toolsexposes Signet signing, verification, and content hashing as MCP tools — plug into any MCP-compatible client:

Available tools:signet_generate_keypair,signet_sign,signet_verify,signet_content_hash.

Python SDK (LangChain / CrewAI / AutoGen + 6 more)

from 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}")

For plain Python tools, the lowest-friction entry point is the decorator layer:

from signet_auth import SigningAgent, signet_tool agent = SigningAgent.create("tool-bot", owner="team") @signet_tool(agent=agent, target="mcp://github.prod", audit_encrypt_params=True) def create_issue(title: str, repo: str) -> str: return f"{repo}:{title}"

If you run a Python MCP server or other execution boundary, useverify_request()with a durable nonce backend in the pilot shape:

from signet_auth import FileNonceChecker, VerifyOptions, verify_request nonce_checker = FileNonceChecker(".signet/nonces.json") opts = VerifyOptions( trusted_keys=["ed25519:..."], expected_target="mcp://github.prod", nonce_checker=nonce_checker, ) result = verify_request(request_params, opts) if not result.ok: raise ValueError(result.error or "verification failed") if not result.trusted: raise ValueError("untrusted signer")
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 AsyncSignetCallbackHandler
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()
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 uses LangChain's callback system — the same handler works directly:

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]})
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)
No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.