{"id":48116763,"url":"https://github.com/prismer-ai/signet","last_synced_at":"2026-04-26T13:04:46.264Z","repository":{"id":347896837,"uuid":"1194950905","full_name":"Prismer-AI/signet","owner":"Prismer-AI","description":"Proof layer for AI agents. Cryptographically verify every action.","archived":false,"fork":false,"pushed_at":"2026-04-19T13:23:50.000Z","size":34381,"stargazers_count":32,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-19T14:34:43.051Z","etag":null,"topics":["agent-security","ai-agents","audit-trail","autogen","claude-code","crewai","cryptographic-signing","cursor","ed25519","langchain","mcp","mcp-security","mcp-tools","open-source","python","rust","security","signing","typescript","wasm"],"latest_commit_sha":null,"homepage":"https://github.com/Prismer-AI/signet","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Prismer-AI.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-29T02:45:57.000Z","updated_at":"2026-04-19T13:23:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Prismer-AI/signet","commit_stats":null,"previous_names":["prismer-ai/signet"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/Prismer-AI/signet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prismer-AI%2Fsignet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prismer-AI%2Fsignet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prismer-AI%2Fsignet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prismer-AI%2Fsignet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Prismer-AI","download_url":"https://codeload.github.com/Prismer-AI/signet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prismer-AI%2Fsignet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32297940,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-security","ai-agents","audit-trail","autogen","claude-code","crewai","cryptographic-signing","cursor","ed25519","langchain","mcp","mcp-security","mcp-tools","open-source","python","rust","security","signing","typescript","wasm"],"created_at":"2026-04-04T16:16:22.289Z","updated_at":"2026-04-26T13:04:46.226Z","avatar_url":"https://github.com/Prismer-AI.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eSignet\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eDon't just log agent actions. Prove them.\u003c/strong\u003e\u003cbr/\u003e\n  \u003csub\u003eCryptographic receipts for every AI agent tool call — signed, hash-chained, offline-verifiable. Independent of any provider.\u003c/sub\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/Prismer-AI/signet/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/Prismer-AI/signet/ci.yml?branch=main\u0026style=flat-square\u0026labelColor=black\u0026label=CI\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/Prismer-AI/signet/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/Prismer-AI/signet?style=flat-square\u0026labelColor=black\u0026color=green\u0026label=release\" alt=\"Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/Prismer-AI/signet/blob/main/LICENSE-APACHE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-Apache--2.0%20%2F%20MIT-blue?labelColor=black\u0026style=flat-square\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/Prismer-AI/signet/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/Prismer-AI/signet?style=flat-square\u0026labelColor=black\u0026color=yellow\" alt=\"Stars\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codespaces.new/Prismer-AI/signet?quickstart=1\"\u003e\u003cimg src=\"https://img.shields.io/badge/Try_it-Open_in_Codespaces-black?style=flat-square\u0026logo=github\" alt=\"Open in Codespaces\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/SDKs-333?style=flat-square\" alt=\"SDKs\"\u003e\n  \u003ca href=\"https://crates.io/crates/signet-core\"\u003e\u003cimg src=\"https://img.shields.io/crates/v/signet-core?style=flat-square\u0026labelColor=black\u0026color=dea584\u0026logo=rust\u0026logoColor=white\u0026label=signet--core\" alt=\"crates.io\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/signet-auth/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/signet-auth?style=flat-square\u0026labelColor=black\u0026color=3775A9\u0026logo=python\u0026logoColor=white\u0026label=signet--auth\" alt=\"PyPI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/org/signet-auth\"\u003e\u003cimg src=\"https://img.shields.io/badge/npm-6%20packages-cb3837?style=flat-square\u0026labelColor=black\u0026logo=npm\u0026logoColor=white\" alt=\"npm packages\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003e\n    TypeScript packages:\n    \u003ca href=\"https://www.npmjs.com/package/@signet-auth/core\"\u003e\u003ccode\u003e@signet-auth/core\u003c/code\u003e\u003c/a\u003e ·\n    \u003ca href=\"https://www.npmjs.com/package/@signet-auth/mcp\"\u003e\u003ccode\u003e@signet-auth/mcp\u003c/code\u003e\u003c/a\u003e ·\n    \u003ca href=\"https://www.npmjs.com/package/@signet-auth/mcp-server\"\u003e\u003ccode\u003e@signet-auth/mcp-server\u003c/code\u003e\u003c/a\u003e ·\n    \u003ca href=\"https://www.npmjs.com/package/@signet-auth/mcp-tools\"\u003e\u003ccode\u003e@signet-auth/mcp-tools\u003c/code\u003e\u003c/a\u003e ·\n    \u003ca href=\"https://www.npmjs.com/package/@signet-auth/node\"\u003e\u003ccode\u003e@signet-auth/node\u003c/code\u003e\u003c/a\u003e ·\n    \u003ca href=\"https://www.npmjs.com/package/@signet-auth/vercel-ai\"\u003e\u003ccode\u003e@signet-auth/vercel-ai\u003c/code\u003e\u003c/a\u003e\n  \u003c/sub\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"./README.md\"\u003e\u003cimg alt=\"English\" src=\"https://img.shields.io/badge/English-d9d9d9\"\u003e\u003c/a\u003e\n  \u003ca href=\"./README.zh.md\"\u003e\u003cimg alt=\"简体中文\" src=\"https://img.shields.io/badge/简体中文-d9d9d9\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.youtube.com/watch?v=7OiGV_pyZas\"\u003e\n    \u003cimg src=\"https://img.youtube.com/vi/7OiGV_pyZas/maxresdefault.jpg\" alt=\"Watch the Signet walkthrough on YouTube\" width=\"820\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003e\u003ca href=\"https://www.youtube.com/watch?v=7OiGV_pyZas\"\u003e▶ Walkthrough: signing, audit log, and verification\u003c/a\u003e · \u003ca href=\"https://www.youtube.com/watch?v=PQnZC594qZc\"\u003e▶ Demo: execution boundary \u0026amp; MCP integration\u003c/a\u003e\u003c/sub\u003e\n\u003c/p\u003e\n\n**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?**\n\nSignet is the **independent verification layer** for 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.\n\n\u003e **Your agents run on their infrastructure. The proof belongs to you.**\n\n## Why Not Just Logs?\n\nTraditional logs tell you what a platform **says** happened. They're mutable, provider-dependent, and unverifiable without trusting the party that wrote them.\n\nSignet 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.\n\n| Ordinary logs | Signet receipts |\n| --- | --- |\n| Provider says it happened | Anyone can verify it, offline |\n| Mutable after the fact | Signature breaks on tamper |\n| No ordering proof | Hash chain breaks on delete/reorder |\n| Trust the log host | Verify with the public key |\n| One-sided claim | Bilateral co-signing available |\n\nUse logs for observability. Use Signet when you need **evidence**.\n\n## Who Is This For?\n\n- **MCP builders** — wrap any MCP server with `signet proxy`, sign every `tools/call`, no code changes\n- **Security / compliance teams** — tamper-evident audit trail that satisfies EU AI Act Art. 12, SOC 2 CC7.2, ISO 27001 A.8.15\n- **Enterprise agent platforms** — prove what the agent did, who authorized it, which policy was in force\n- **Framework users** — LangChain, CrewAI, Claude Code, Codex, OpenAI Agents, Vercel AI SDK — all supported\n- **Agent-to-agent deployments** — bilateral co-signing when both sides hold keys\n\n**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.\"\n\nEach 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.\n\nThe video above shows the full flow. The SVG below shows the CLI signing details, or jump to [See It Reject Bad Requests](#execution-boundary-demo) to watch the server block bad requests before they run.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo-cli.svg\" alt=\"Signet demo\" width=\"820\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eThis first demo shows signing + audit receipts. See also the \u003ca href=\"./demo-mcp.svg\"\u003eMCP flow diagram\u003c/a\u003e.\u003c/sub\u003e\n\u003c/p\u003e\n\n## What Signet Adds\n\nSignet adds a lightweight trust layer for agent actions:\n\n- **Sign** every tool call with the agent's cryptographic key\n- **Verify** requests offline or at the execution boundary before they are trusted\n- **Proxy** any MCP server transparently — sign and co-sign without touching agent or server code\n- **Co-sign** server responses with bilateral receipts when you control both sides\n- **Trace** multi-step workflows by linking receipts with `trace_id` and `parent_receipt_id`\n- **Authorize** agents with scoped delegation chains that prove who allowed the action\n- **Attest policy** by embedding a signed `PolicyAttestation` when a YAML policy is satisfied\n- **Inspect locally** with an append-only audit log and dashboard, no hosted control plane required\n\n## What's New In 0.9\n\n- **MCP proxy**: `signet proxy --target \u003ccmd\u003e --key \u003cname\u003e` — drop Signet in front of any MCP server as a transparent stdio proxy. No changes to the agent or server required. Signs every `tools/call` and co-signs server responses with bilateral receipts.\n- **Trace correlation**: `trace_id` and `parent_receipt_id` fields on `Action` link receipts across multi-step workflows into a causal chain. Both fields are part of the signed payload — tampering invalidates the signature.\n- **Policy engine**: `signet sign --policy policy.yaml` enforces policy before signing and binds the decision into the receipt. The proxy also respects `--policy`, blocking denied calls before they reach the server.\n- **Delegation chains**: `signet delegate ...` produces v4 receipts that prove who authorized the agent and what scope it had.\n- **Local dashboard**: `signet dashboard` shows timeline, chain integrity, signature health, and delegated vs direct activity.\n- **Broader integrations**: official Claude Code plugin, Codex plugin, MCP middleware, Python SDK, and Vercel AI SDK callbacks.\n\n## Compliance\n\nSignet provides the technical controls that auditors look for when assessing AI agent operations. See the full [Compliance Mapping](docs/COMPLIANCE.md) for details.\n\n| Framework | What Signet Addresses |\n|-----------|---------------------|\n| **SOC 2 Type II** | Signed audit trail (CC7.2), tamper detection (CC7.3), role-based scope (CC6.3), authorization proof (CC8.1) |\n| **ISO 27001** | Event logging (A.8.15), access control (A.5.15), authentication (A.5.17), configuration management (A.8.9) |\n| **EU AI Act** | Article 12 record-keeping: event logging, traceability, identification, integrity |\n| **DORA** | ICT incident logging (Art. 17), third-party risk evidence (Art. 28-30), audit trail integrity |\n| **NIST AI RMF** | Govern (delegation chains), Map (signed receipts), Measure (audit queries), Manage (policy engine) |\n\n\u003e Signet is a tool, not a certification. It provides controls that support compliance — your deployment and configuration determine compliance posture.\n\n## Try It In 30 Seconds\n\n```bash\npip install signet-auth\n```\n\n```python\nfrom signet_auth import SigningAgent\n\nagent = SigningAgent.create(\"my-agent\", owner=\"team\")\nreceipt = agent.sign(\"github_create_issue\", params={\"title\": \"fix bug\"})\n\nassert agent.verify(receipt)\nprint(receipt.id)\n```\n\n## Why Star This Repo?\n\nSignet 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.\n\n- Working with **Microsoft Agent Governance Toolkit** (example merged in [PR #1196](https://github.com/microsoft/agent-governance-toolkit/pull/1196))\n- Named contributor in **LangChain's ComplianceBackend RFC** ([#35691](https://github.com/langchain-ai/langchain/issues/35691))\n- Conformance work toward the **IETF draft-farley-acta-signed-receipts** spec\n- Maps to **NIST NCCoE's four pillars** for AI agent identity and authorization (Q4 2026 Interoperability Profile)\n\nIf 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.\n\nIf you're new, start with one of these five paths:\n\n## Choose Your Path\n\n- [**Claude Code**](#claude-code-plugin): Best for the fastest first run in a coding agent. Run `/plugin install signet@claude-plugins-official` in Claude Code. In 5 minutes you'll have signed tool calls and a local audit log at `~/.signet/audit/`.\n- [**Codex CLI**](#codex-plugin): Best for signing Bash tool calls in Codex. Copy `plugins/codex/` into `~/.codex/plugins/signet` and add one `PostToolUse` hook. In 5 minutes you'll have signed Bash actions in Codex using the same audit trail.\n- [**Python SDK**](#python-sdk): Best if you want receipts inside LangGraph, LlamaIndex, OpenAI Agents, CrewAI, or your own tool runner. Start with `SigningAgent.create(...)` and add framework hooks only where you need them.\n- [**MCP clients**](#mcp-client-integration): Best if you control an MCP client or transport. Wrap your transport with `new SigningTransport(inner, secretKey, \"my-agent\")`. In 5 minutes you'll have signed `tools/call` requests with receipts in `params._meta._signet`.\n- [**MCP servers**](#mcp-server-verification): Best if you want verification before execution. Call `verifyRequest(request, {...})` in your tool handler. In 5 minutes you'll have signer, freshness, target-binding, and tool/params checks at the execution boundary.\n\n\u003ca id=\"execution-boundary-demo\"\u003e\u003c/a\u003e\n## See It Reject Bad Requests\n\nRun the shortest execution-boundary demo:\n\n```bash\ncd examples/mcp-agent\nnpm run execution-boundary-demo\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo-execution-boundary.svg\" alt=\"Execution-boundary demo showing invalid requests rejected before execution\" width=\"820\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003ePrefer motion? Download the \u003ca href=\"./demo-execution-boundary.mp4\"\u003eMP4\u003c/a\u003e or \u003ca href=\"./demo-execution-boundary.gif\"\u003eGIF\u003c/a\u003e.\u003c/sub\u003e\n\u003c/p\u003e\n\nSee [examples/mcp-agent/demo-execution-boundary.mjs](./examples/mcp-agent/demo-execution-boundary.mjs) for the demo source.\n\n\u003ca id=\"delegation-chains\"\u003e\u003c/a\u003e\n## Delegation Chains: Who Authorized This Agent?\n\nSignet receipts prove **what** happened. Delegation chains prove **who allowed it**.\n\nA 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.\n\n```text\nOwner (alice) → Agent A (tools: [Bash, Read], max_depth: 0)\n                    ↓\n              v4 Receipt: tool=Bash, authorization.chain proves alice → Agent A\n```\n\n```bash\n# Create a delegation token (expires in 24 hours)\nsignet delegate create --from alice --to deploy-bot --to-name deploy-bot \\\n    --tools Bash,Read --targets \"mcp://github\" --max-depth 0 --ttl 24h\n\n# Sign with authorization proof (v4 receipt)\nsignet delegate sign --key deploy-bot --tool Bash \\\n    --params '{\"cmd\":\"git pull\"}' --target \"mcp://github\" --chain chain.json\n\n# Verify: signature + chain + scope + root trust\nsignet delegate verify-auth receipt.json --trusted-roots alice\n```\n\n\u003e **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.\n\nOr in Python:\n\n```python\nfrom signet_auth import sign_delegation, sign_authorized, verify_authorized\n\n# Delegation functions accept JSON strings for scope, chain, and receipts\ntoken_json = sign_delegation(root_key_b64, \"alice\", agent_pubkey_b64, \"bot\", scope_json)\nreceipt_json = sign_authorized(agent_key_b64, action_json, \"bot\", f\"[{token_json}]\")\nscope_json = verify_authorized(receipt_json, [root_pubkey_b64])\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo-delegation.svg\" alt=\"Delegation chain demo\" width=\"820\"\u003e\n\u003c/p\u003e\n\n## Policy Attestations: Was This Allowed?\n\nSignet can enforce a YAML policy before signing. When an action is allowed, the signed receipt carries a `PolicyAttestation` proving which policy hash, rule, and decision were in force.\n\n```yaml\nversion: 1\nname: production-agents\ndefault_action: deny\nrules:\n  - id: allow-read\n    match:\n      tool: Read\n    action: allow\n  - id: deny-rm-rf\n    match:\n      tool: Bash\n      params:\n        command:\n          contains: \"rm -rf\"\n    action: deny\n    reason: destructive command\n```\n\n```bash\nsignet policy validate policy.yaml\nsignet policy check policy.yaml --tool Bash --params '{\"command\":\"rm -rf /\"}'\n\nsignet sign --key deploy-bot --tool Read \\\n    --params '{\"path\":\"README.md\"}' --target \"mcp://github\" --policy policy.yaml\n```\n\nDenied actions fail before a receipt is produced. Allowed actions produce a receipt whose signed payload proves the policy decision.\n\n## When Teams Reach For Signet\n\n- You need a tamper-evident audit trail for coding agents, MCP tools, or CI automation\n- You want to prove which agent requested an action and who authorized it after an incident\n- You need receipts that can be verified offline without depending on a hosted service\n- You want lightweight policy enforcement before signing without adding a proxy to your stack\n\n## What Signet Is And Isn't\n\n- **Signet is** a trust layer for agent actions: signing, audit, verification, delegation, and policy attestation\n- **Signet is** designed to fit into existing agent stacks with SDKs, plugins, and MCP middleware\n- **Signet can** reject unsigned, stale, replayed, or mis-targeted MCP requests before execution\n- **Signet can** deny actions before signing when you provide a policy file\n- **Signet is not** a hosted gateway, always-on control plane, or replacement for sandboxing and least-privilege design\n\n## Install\n\n```bash\n# CLI\ncargo install signet-cli\n\n# Python\npip install signet-auth\n\n# TypeScript (MCP middleware)\nnpm install @signet-auth/core @signet-auth/mcp\n\n# TypeScript (MCP server verification)\nnpm install @signet-auth/mcp-server\n\n# TypeScript (Node local audit/operator helpers)\nnpm install @signet-auth/node\n\n# TypeScript (Vercel AI SDK middleware)\nnpm install @signet-auth/vercel-ai\n\n# TypeScript (standalone MCP signing server)\nnpx @signet-auth/mcp-tools\n```\n\n## Quick Start\n\n\u003ca id=\"claude-code-plugin\"\u003e\u003c/a\u003e\n### Claude Code Plugin\n\nAuto-sign every tool call in [Claude Code](https://claude.ai/code) with zero configuration:\n\n```bash\n# Option A: From the official Anthropic plugin marketplace\n/plugin install signet@claude-plugins-official\n\n# Option B: Add Signet as a marketplace source, then install\n/plugin marketplace add Prismer-AI/signet\n/plugin install signet@signet\n```\n\nEvery tool call is signed with Ed25519 and logged to a hash-chained audit trail at `~/.signet/audit/`.\n\nAlternative install methods:\n\n```bash\n# From Git\nclaude plugin add --from https://github.com/Prismer-AI/signet\n\n# Via signet CLI\nsignet claude install\n```\n\n\u003ca id=\"codex-plugin\"\u003e\u003c/a\u003e\n### Codex Plugin\n\nAuto-sign every Bash tool call in [Codex CLI](https://github.com/openai/codex):\n\n```bash\ngit clone https://github.com/Prismer-AI/signet.git\ncp -r signet/plugins/codex ~/.codex/plugins/signet\n```\n\nThen add the hook to `~/.codex/hooks.json`:\n\n```json\n{\n  \"hooks\": {\n    \"PostToolUse\": [{\n      \"matcher\": \"Bash\",\n      \"hooks\": [{\n        \"type\": \"command\",\n        \"command\": \"node \\\"$HOME/.codex/plugins/signet/bin/sign.cjs\\\"\",\n        \"timeout\": 5\n      }]\n    }]\n  }\n}\n```\n\nOr use the MCP server for on-demand signing tools:\n\n```bash\ncodex mcp add signet -- npx @signet-auth/mcp-tools\n```\n\n### CLI\n\n```bash\n# Generate an agent identity\nsignet identity generate --name my-agent\n\n# Sign an action\nsignet sign --key my-agent --tool \"github_create_issue\" \\\n  --params '{\"title\":\"fix bug\"}' --target mcp://github.local\n\n# Verify a receipt\nsignet verify receipt.json --pubkey my-agent\n\n# Audit recent actions\nsignet audit --since 24h\n\n# Verify log integrity\nsignet verify --chain\n```\n\n\u003ca id=\"mcp-client-integration\"\u003e\u003c/a\u003e\n### MCP Client Integration (TypeScript)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo-mcp.svg\" alt=\"Signet MCP bilateral flow demo\" width=\"820\"\u003e\n\u003c/p\u003e\n\n```typescript\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { generateKeypair } from \"@signet-auth/core\";\nimport { SigningTransport } from \"@signet-auth/mcp\";\n\n// Generate an agent identity\nconst { secretKey } = generateKeypair();\n\n// Wrap any MCP transport -- all tool calls are now signed\nconst inner = new StdioClientTransport({ command: \"my-mcp-server\" });\nconst transport = new SigningTransport(inner, secretKey, \"my-agent\");\n\nconst client = new Client({ name: \"my-agent\", version: \"1.0\" }, {});\nawait client.connect(transport);\n\n// Every callTool() is now cryptographically signed\nconst result = await client.callTool({\n  name: \"echo\",\n  arguments: { message: \"Hello!\" },\n});\n```\n\nEvery `tools/call` request gets a signed receipt injected into `params._meta._signet`.\n\n\u003ca id=\"mcp-server-verification\"\u003e\u003c/a\u003e\n### MCP Server Verification\n\nIf you control the MCP server too, verify requests before execution:\n\n```typescript\nimport { verifyRequest } from \"@signet-auth/mcp-server\";\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) =\u003e {\n  const verified = verifyRequest(request, {\n    trustedKeys: [\"ed25519:...\"],\n    maxAge: 300,\n  });\n  if (!verified.ok) return { content: [{ type: \"text\", text: verified.error }], isError: true };\n  if (!verified.trusted) return { content: [{ type: \"text\", text: \"untrusted signer\" }], isError: true };\n  console.log(`Verified: ${verified.signerName}`);\n  // process tool call...\n});\n```\n\n### Vercel AI SDK Integration\n\n```typescript\nimport { generateText } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport { generateKeypair } from \"@signet-auth/core\";\nimport { createSignetCallbacks } from \"@signet-auth/vercel-ai\";\n\nconst { secretKey } = generateKeypair();\nconst callbacks = createSignetCallbacks(secretKey, \"my-agent\");\n\nconst result = await generateText({\n  model: openai(\"gpt-4o\"),\n  tools: { myTool },\n  ...callbacks,\n  prompt: \"...\",\n});\n\n// Every tool call is now signed\nconsole.log(callbacks.receipts);\n```\n\n### Reference MCP Server\n\nThis repo also includes a minimal MCP reference server that demonstrates server-side verification with `@signet-auth/mcp-server`.\n\n```bash\ncd examples/mcp-agent\nnpm ci\nnpm run verifier-server\n```\n\nAvailable tools:\n\n- `inspect_current_request` — verifies the current MCP tool call if it includes `params._meta._signet`\n- `verify_receipt` — verifies a raw Signet receipt against a public key\n- `verify_request_payload` — verifies a synthetic MCP `tools/call` payload offline\n\nEnvironment variables:\n\n- `SIGNET_TRUSTED_KEYS` — comma-separated `ed25519:\u003cbase64\u003e` public keys\n- `SIGNET_REQUIRE_SIGNATURE` — `true` or `false` (default `true`)\n- `SIGNET_REQUIRE_TRUSTED_SIGNER` — `true` or `false` (default `true`)\n- `SIGNET_MAX_AGE` — max receipt age in seconds (default `300`)\n- `SIGNET_EXPECTED_TARGET` — optional expected `receipt.action.target`\n\n### Standalone MCP Signing Server\n\n`@signet-auth/mcp-tools` exposes Signet signing, verification, and content hashing as MCP tools — plug into any MCP-compatible client:\n\n```bash\nnpx @signet-auth/mcp-tools\n```\n\nAvailable tools: `signet_generate_keypair`, `signet_sign`, `signet_verify`, `signet_content_hash`.\n\n\u003ca id=\"python-sdk\"\u003e\u003c/a\u003e\n### Python SDK (LangChain / CrewAI / AutoGen + 6 more)\n\n```bash\npip install signet-auth\n```\n\n```python\nfrom signet_auth import SigningAgent\n\n# Create an agent identity (saved to ~/.signet/keys/)\nagent = SigningAgent.create(\"my-agent\", owner=\"willamhou\")\n\n# Sign any tool call -- receipt is auto-appended to audit log\nreceipt = agent.sign(\"github_create_issue\", params={\"title\": \"fix bug\"})\n\n# Verify\nassert agent.verify(receipt)\n\n# Query audit log\nfor record in agent.audit_query(since=\"24h\"):\n    print(f\"{record.receipt.ts} {record.receipt.action.tool}\")\n```\n\n#### LangChain Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.langchain import SignetCallbackHandler\n\nagent = SigningAgent(\"my-agent\")\nhandler = SignetCallbackHandler(agent)\n\n# Every tool call is now signed + audited\nchain.invoke(input, config={\"callbacks\": [handler]})\n\n# Async chains supported too\nfrom signet_auth.langchain import AsyncSignetCallbackHandler\n```\n\n#### CrewAI Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.crewai import install_hooks\n\nagent = SigningAgent(\"my-agent\")\ninstall_hooks(agent)\n\n# All CrewAI tool calls are now globally signed\ncrew.kickoff()\n```\n\n#### AutoGen Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.autogen import signed_tool, sign_tools\n\nagent = SigningAgent(\"my-agent\")\n\n# Wrap a single tool\nwrapped = signed_tool(tool, agent)\n\n# Or wrap all tools at once\nwrapped_tools = sign_tools([tool1, tool2], agent)\n```\n\n#### LangGraph Integration\n\nLangGraph uses LangChain's callback system — the same handler works directly:\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.langgraph import SignetCallbackHandler\n\nagent = SigningAgent(\"my-agent\")\nhandler = SignetCallbackHandler(agent)\n\nresult = graph.invoke(input, config={\"callbacks\": [handler]})\n```\n\n#### LlamaIndex Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.llamaindex import install_handler\n\nagent = SigningAgent(\"my-agent\")\nhandler = install_handler(agent)\n\n# All tool call events are now signed\nindex = ... # your LlamaIndex setup\nresponse = index.as_query_engine().query(\"What is Signet?\")\n\n# Access receipts\nprint(handler.receipts)\n```\n\n#### Pydantic AI Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.pydantic_ai_integration import SignetMiddleware\n\nagent = SigningAgent(\"my-agent\")\nmiddleware = SignetMiddleware(agent)\n\n@middleware.wrap\ndef my_tool(query: str) -\u003e str:\n    return f\"result: {query}\"\n```\n\n#### Google ADK Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.google_adk import SignetPlugin\n\nagent = SigningAgent(\"my-agent\")\nplugin = SignetPlugin(agent)\n\n# Pass as callback to ADK agent\n```\n\n#### Smolagents Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.smolagents import signet_step_callback\n\nagent = SigningAgent(\"my-agent\")\ncallback = signet_step_callback(agent)\n\nbot = CodeAgent(tools=[...], model=model, step_callbacks=[callback])\n```\n\n#### OpenAI Agents SDK Integration\n\n```python\nfrom signet_auth import SigningAgent\nfrom signet_auth.openai_agents import SignetAgentHooks\n\nagent = SigningAgent(\"my-agent\")\n\noai_agent = Agent(\n    name=\"assistant\",\n    hooks=SignetAgentHooks(agent),\n    tools=[...],\n)\n```\n\n\u003e **Note:** Tool call arguments are not yet available in the hook API ([issue #939](https://github.com/openai/openai-agents-python/issues/939)). Only the tool name is signed.\n\n#### Low-Level API\n\n```python\nfrom signet_auth import generate_keypair, sign, verify, Action\n\nkp = generate_keypair()\naction = Action(\"github_create_issue\", params={\"title\": \"fix bug\"})\nreceipt = sign(kp.secret_key, action, \"my-agent\", \"willamhou\")\nassert verify(receipt, kp.public_key)\n```\n\n#### Bilateral Receipt (Server Co-signing)\n\n```python\nfrom signet_auth import generate_keypair, sign, sign_bilateral, verify_bilateral, Action\n\n# Agent signs the tool call\nagent_kp = generate_keypair()\naction = Action(\"github_create_issue\", params={\"title\": \"fix bug\"})\nagent_receipt = sign(agent_kp.secret_key, action, \"my-agent\")\n\n# Server co-signs with the response\nserver_kp = generate_keypair()\nbilateral = sign_bilateral(\n    server_kp.secret_key, agent_receipt,\n    {\"content\": [{\"type\": \"text\", \"text\": \"issue #42 created\"}]},\n    \"github-server\",\n)\nassert verify_bilateral(bilateral, server_kp.public_key)\nassert bilateral.v == 3  # v3 = bilateral receipt\n```\n\n## How It Works\n\n```\nYour Agent\n    |\n    v\nSigningTransport (wraps any MCP transport)\n    |\n    +---\u003e Signs each tool call (Ed25519)\n    +---\u003e Appends Action Receipt to local audit log (hash-chained)\n    +---\u003e Forwards request to MCP server (unchanged)\n```\n\nClient-side signing works without changing the server. If you control the server too, add `verifyRequest()` and optional `signResponse()` for execution-boundary verification and bilateral receipts. `signResponse()` should only run after a successful trusted `verifyRequest()`.\n\n## Action Receipt\n\nEvery tool call starts with a signed receipt. Higher receipt versions add server co-signing (v3) and authorization chains (v4):\n\n```json\n{\n  \"v\": 1,\n  \"id\": \"rec_e7039e7e7714e84f...\",\n  \"action\": {\n    \"tool\": \"github_create_issue\",\n    \"params\": {\"title\": \"fix bug\"},\n    \"params_hash\": \"sha256:b878192252cb...\",\n    \"target\": \"mcp://github.local\",\n    \"transport\": \"stdio\"\n  },\n  \"signer\": {\n    \"pubkey\": \"ed25519:0CRkURt/tc6r...\",\n    \"name\": \"demo-bot\",\n    \"owner\": \"willamhou\"\n  },\n  \"ts\": \"2026-03-29T23:24:03.309Z\",\n  \"nonce\": \"rnd_dcd4e135799393...\",\n  \"sig\": \"ed25519:6KUohbnSmehP...\"\n}\n```\n\nThe signature covers the entire receipt body (action + signer + timestamp + nonce) using [RFC 8785 (JCS)](https://datatracker.ietf.org/doc/html/rfc8785) canonical JSON. Modifying any field invalidates the signature.\n\n## CLI Commands\n\n| Command | Description |\n|---------|-------------|\n| `signet identity generate --name \u003cn\u003e` | Generate Ed25519 identity (encrypted by default) |\n| `signet identity generate --unencrypted` | Generate without encryption (for CI) |\n| `signet identity list` | List all identities |\n| `signet identity export --name \u003cn\u003e` | Export public key as JSON |\n| `signet sign --key \u003cn\u003e --tool \u003ct\u003e --params \u003cjson\u003e --target \u003curi\u003e` | Sign an action |\n| `signet sign --hash-only` | Store only params hash (not raw params) |\n| `signet sign --output \u003cfile\u003e` | Write receipt to file instead of stdout |\n| `signet sign --no-log` | Skip audit log append |\n| `signet sign --encrypt-params` | Encrypt `action.params` in the audit log while keeping the receipt output unchanged |\n| `signet sign --policy \u003cpath\u003e` | Enforce policy before signing and embed `PolicyAttestation` |\n| `signet verify \u003creceipt.json\u003e --pubkey \u003cname\u003e` | Verify a receipt signature |\n| `signet verify --chain` | Verify audit log hash chain integrity |\n| `signet audit` | List recent actions |\n| `signet audit --since \u003cduration\u003e` | Filter by time (e.g. 24h, 7d) |\n| `signet audit --tool \u003csubstring\u003e` | Filter by tool name |\n| `signet audit --verify` | Verify all receipt signatures |\n| `signet audit --export \u003cfile\u003e` | Export records as JSON |\n| `signet audit --export \u003cfile\u003e --decrypt-params` | Export original audit records plus `materialized_receipt` with decrypted params |\n| `signet explore` | Browse receipts interactively (table, detail, stats, chain check) |\n| `signet explore --show N` | Inspect receipt #N with signature, policy, and chain info |\n| `signet explore --show N --decrypt-params` | Materialize encrypted `action.params` for local inspection |\n| `signet explore --stats` | Receipt statistics by tool, signer, and version |\n| `signet delegate create ... --ttl 24h` | Create a scoped delegation token (short-lived) |\n| `signet delegate sign ... --chain \u003cfile\u003e` | Sign with delegation proof and produce a v4 receipt |\n| `signet delegate verify-auth \u003creceipt\u003e --trusted-roots \u003cname\u003e` | Verify authorization chain, scope, and trusted root |\n| `signet policy validate \u003cpath\u003e` | Validate policy syntax and print its hash |\n| `signet policy check \u003cpath\u003e --tool \u003ct\u003e --params \u003cjson\u003e` | Dry-run whether an action would be allowed |\n| `signet proxy --target \u003ccmd\u003e --key \u003cname\u003e` | Run as MCP stdio proxy — sign all tool calls transparently |\n| `signet proxy --target \u003ccmd\u003e --key \u003cn\u003e --policy \u003cpath\u003e` | Proxy with policy enforcement before signing |\n| `signet claude install` | Install Claude Code plugin (PostToolUse signing hook) |\n| `signet claude uninstall` | Remove Claude Code plugin |\n| `signet dashboard` | Open local audit dashboard in browser |\n\nPassphrase via interactive prompt or `SIGNET_PASSPHRASE` env var for CI.\n\n## Audit Dashboard\n\nRun `signet dashboard` to open a local web UI for your audit log — no account, no network, just your local receipts.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"dashboard-timeline.png\" alt=\"Signet audit dashboard — timeline view showing every signed tool call\" width=\"820\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eTimeline view: every tool call logged with signer, tool name, target, and receipt ID. Filter by time, tool, or signer.\u003c/sub\u003e\n\u003c/p\u003e\n\nThe **Chain Integrity** tab verifies the SHA-256 hash chain across your entire audit log — any tampering or gap is pinpointed to the exact file and line:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"dashboard-chain-integrity.png\" alt=\"Signet chain integrity check — break point detected at line 189\" width=\"820\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eChain broken at line 189: expected vs actual hash shown. This is what \"append-only\" actually looks like in practice.\u003c/sub\u003e\n\u003c/p\u003e\n\n## Documentation\n\n| Doc | Description |\n|-----|-------------|\n| [Architecture](docs/ARCHITECTURE.md) | System design, component overview, data flow |\n| [Security](docs/SECURITY.md) | Crypto primitives, threat model, key storage |\n| [MCP Integration Guide](docs/guides/mcp-integration.md) | Step-by-step MCP setup with SigningTransport |\n| [CI/CD Integration](docs/guides/ci-integration.md) | GitHub Actions example, key management for CI |\n| [Audit Log Guide](docs/guides/audit-log.md) | Querying, filtering, hash chain verification |\n| [Contributing](CONTRIBUTING.md) | Build instructions, development workflow |\n| [Changelog](CHANGELOG.md) | Version history |\n\n## Project Structure\n\n```\nsignet/\n├── crates/signet-core/       Rust core: identity, sign, verify, audit, keystore\n├── signet-cli/               CLI tool (signet binary)\n├── bindings/\n│   ├── signet-ts/            WASM binding (wasm-bindgen)\n│   └── signet-py/            Python binding (PyO3 + maturin)\n├── plugins/\n│   ├── claude-code/          Claude Code plugin (WASM signing + audit)\n│   └── codex/                Codex CLI plugin (WASM signing + audit)\n├── packages/\n│   ├── signet-core/          @signet-auth/core — TypeScript wrapper\n│   ├── signet-mcp/           @signet-auth/mcp — MCP SigningTransport middleware\n│   ├── signet-mcp-server/    @signet-auth/mcp-server — Server verification\n│   ├── signet-mcp-tools/     @signet-auth/mcp-tools — Standalone MCP signing server\n│   ├── signet-node/          @signet-auth/node — Node local audit/operator helpers\n│   └── signet-vercel-ai/     @signet-auth/vercel-ai — Vercel AI SDK middleware\n├── examples/\n│   ├── wasm-roundtrip/       WASM validation tests\n│   └── mcp-agent/            MCP agent, echo server, and verifier server example\n├── docs/                     Design docs, specs, plans\n├── LICENSE-APACHE\n└── LICENSE-MIT\n```\n\n## Building from Source\n\n### Prerequisites\n\n- Rust (1.70+)\n- wasm-pack\n- Node.js (18+)\n- Python (3.10+) + maturin (for Python binding)\n\n### Build\n\n```bash\n# Rust core + CLI\ncargo build --release -p signet-cli\n\n# WASM binding\nwasm-pack build bindings/signet-ts --target nodejs --out-dir ../../packages/signet-core/wasm\n\n# TypeScript packages\ncd packages/signet-core \u0026\u0026 npm run build\ncd packages/signet-mcp \u0026\u0026 npm run build\ncd packages/signet-mcp-server \u0026\u0026 npm run build\ncd packages/signet-mcp-tools \u0026\u0026 npm run build\ncd packages/signet-node \u0026\u0026 npm run build\ncd packages/signet-vercel-ai \u0026\u0026 npm run build\n```\n\n```bash\n# Python binding\ncd bindings/signet-py\npip install maturin\nmaturin develop\n```\n\n### Test\n\n```bash\n# Rust tests\ncargo test --workspace\n\n# Python tests\ncd bindings/signet-py \u0026\u0026 pytest tests/ -v\n\n# WASM roundtrip\nnode examples/wasm-roundtrip/test.mjs\n\n# TypeScript tests\ncd packages/signet-core \u0026\u0026 npm test\ncd packages/signet-mcp \u0026\u0026 npm test\ncd packages/signet-mcp-server \u0026\u0026 npm test\ncd packages/signet-mcp-tools \u0026\u0026 npm test\ncd packages/signet-node \u0026\u0026 npm test\n\n# Plugin tests\ncd plugins/claude-code \u0026\u0026 npm test\ncd plugins/codex \u0026\u0026 npm test\n\n# Vercel AI SDK tests\ncd packages/signet-vercel-ai \u0026\u0026 npm test\n\n# Reference verifier server smoke test\ncd examples/mcp-agent \u0026\u0026 npm run smoke\n```\n\n## Security\n\n- **Ed25519** signatures (128-bit security level, `ed25519-dalek`)\n- **Argon2id** key derivation (OWASP recommended minimum)\n- **XChaCha20-Poly1305** key encryption with authenticated associated data (AAD)\n- **SHA-256 hash chain** for tamper-evident audit log\n- **RFC 8785 (JCS)** canonical JSON for deterministic signatures\n\nKeys stored at `~/.signet/keys/` with `0600` permissions. Override with `SIGNET_HOME` env var.\n\n### What Signet proves\n\n- Agent key X signed intent to call tool Y with params Z at time T\n\n### What Signet does NOT prove (yet)\n\n- That the MCP server executed the action (use bilateral receipts with `signResponse()` for server co-signing — shipped in v0.4)\n- That signer.owner actually controls the key (planned: identity registry)\n\nSignet is first an evidence layer: it proves what happened. It can also enforce checks at the signing boundary and execution boundary, but it does not replace sandboxing, least-privilege design, or human approval where those are required.\n\n## Related Projects\n\n- **[Prismer Cloud](https://github.com/Prismer-AI/PrismerCloud)** — Full agent harness with evolution engine, memory layer, community, and built-in Ed25519/DID identity. Use Prismer Cloud for the complete agent platform; use Signet when you only need the standalone attestation layer.\n- **[Prismer.AI](https://github.com/Prismer-AI/Prismer)** — The open-source AI research platform\n\n## Star History\n\nIf Signet is useful to you, please star this repo — it helps more teams find it.\n\n[![Star History Chart](https://api.star-history.com/svg?repos=Prismer-AI/signet\u0026type=Date)](https://star-history.com/#Prismer-AI/signet\u0026Date)\n\n## License\n\nApache-2.0 + MIT dual license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprismer-ai%2Fsignet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprismer-ai%2Fsignet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprismer-ai%2Fsignet/lists"}