{"id":50903394,"url":"https://github.com/juanfiguera/sello","last_synced_at":"2026-06-16T05:01:15.718Z","repository":{"id":361321836,"uuid":"1252211188","full_name":"juanfiguera/sello","owner":"juanfiguera","description":"Service-signed encrypted receipts for AI agent actions. https://sello.build/","archived":false,"fork":false,"pushed_at":"2026-06-15T06:33:06.000Z","size":2340,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-15T07:04:41.251Z","etag":null,"topics":["ai-agents","audit","cose","hpke","mcp","receipts","transparency-log"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/juanfiguera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"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-05-28T09:46:55.000Z","updated_at":"2026-06-15T06:33:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"b309039c-cc7d-4ce0-b040-cc42bf08f76b","html_url":"https://github.com/juanfiguera/sello","commit_stats":null,"previous_names":["juanfiguera/sello"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/juanfiguera/sello","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juanfiguera%2Fsello","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juanfiguera%2Fsello/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juanfiguera%2Fsello/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juanfiguera%2Fsello/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juanfiguera","download_url":"https://codeload.github.com/juanfiguera/sello/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juanfiguera%2Fsello/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34391703,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["ai-agents","audit","cose","hpke","mcp","receipts","transparency-log"],"created_at":"2026-06-16T05:01:11.963Z","updated_at":"2026-06-16T05:01:15.677Z","avatar_url":"https://github.com/juanfiguera.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Sello banner](https://raw.githubusercontent.com/juanfiguera/sello/main/docs/assets/sello-banner.png)\n\n\u003ch1 align=\"center\"\u003eSello\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/juanfiguera/sello/actions/workflows/ci.yml\"\u003e\u003cimg alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/juanfiguera/sello/ci.yml?branch=main\u0026style=flat-square\u0026label=build\u0026labelColor=0b1011\u0026color=e8f7ef\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/sello\"\u003e\u003cimg alt=\"npm version\" src=\"https://img.shields.io/npm/v/sello?style=flat-square\u0026label=npm\u0026labelColor=0b1011\u0026color=e8f7ef\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/sello/\"\u003e\u003cimg alt=\"PyPI version\" src=\"https://img.shields.io/pypi/v/sello?style=flat-square\u0026label=pypi\u0026labelColor=0b1011\u0026color=e8f7ef\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/sello\"\u003e\u003cimg alt=\"npm downloads\" src=\"https://img.shields.io/npm/dm/sello?style=flat-square\u0026label=downloads\u0026labelColor=0b1011\u0026color=e8f7ef\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"license Apache-2.0\" src=\"https://img.shields.io/npm/l/sello?style=flat-square\u0026label=license\u0026labelColor=0b1011\u0026color=e8f7ef\"\u003e\u003c/a\u003e\n  \u003ca href=\"package.json\"\u003e\u003cimg alt=\"Node.js 22.7 or newer\" src=\"https://img.shields.io/badge/node-%3E%3D22.7-e8f7ef?style=flat-square\u0026labelColor=0b1011\"\u003e\u003c/a\u003e\n  \u003ca href=\"sdks/python/pyproject.toml\"\u003e\u003cimg alt=\"Python 3.9 or newer\" src=\"https://img.shields.io/badge/python-%3E%3D3.9-e8f7ef?style=flat-square\u0026labelColor=0b1011\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://arxiv.org/abs/2606.04193\"\u003e\u003cimg alt=\"arXiv 2606.04193\" src=\"https://img.shields.io/badge/arXiv-2606.04193-e8f7ef?style=flat-square\u0026labelColor=0b1011\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#try-it\"\u003eQuickstart\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#add-sello-to-a-tool\"\u003eAdd Sello\u003c/a\u003e \u0026middot;\n  \u003ca href=\"docs/mcp.md\"\u003eMCP\u003c/a\u003e \u0026middot;\n  \u003ca href=\"sdks/README.md\"\u003eSDKs\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#see-logged-actions\"\u003eActions\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#how-it-works\"\u003eHow It Works\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#learn-more\"\u003eLearn More\u003c/a\u003e \u0026middot;\n  \u003ca href=\"SPEC.md\"\u003eProtocol\u003c/a\u003e \u0026middot;\n  \u003ca href=\"https://arxiv.org/abs/2606.04193\"\u003ePaper\u003c/a\u003e \u0026middot;\n  \u003ca href=\"SECURITY.md\"\u003eSecurity\u003c/a\u003e \u0026middot;\n  \u003ca href=\"CONTRIBUTING.md\"\u003eContributing\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\n\u003c/p\u003e\n\nSello is a protocol for independently-verifiable records of AI agent actions.\n\n**Pronunciation:** commonly `SEH-yoh` or `SEH-yo`, from the Spanish word *sello*, meaning a seal or stamp.\n\nWhen an agent calls a service, the service creates a receipt for what it observed. The receipt is encrypted to the agent owner, signed by the service, and published to a transparency log. Later, the owner can retrieve and verify that receipt without trusting the agent's own logs.\n\n```text\nagent calls service\n  -\u003e service creates encrypted signed receipt\n  -\u003e transparency log stores receipt\n  -\u003e owner fetches, verifies, decrypts\n```\n\n## Try It\n\nRequires Node.js 22.7 or newer.\n\nFrom a new project or temporary folder:\n\n```bash\n# Terminal 1\nnpx --yes sello dev\n\n# Terminal 2\nnpx --yes sello emit-demo\nnpx --yes sello actions\n```\n\nThen open:\n\n```text\nhttp://localhost:8787/actions\n```\n\n`sello dev` creates local keys, a demo token, a service registry, and a local transparency log under `.sello/`. The log stores encrypted receipt entries, not plaintext action details.\n\n## Add Sello to a Tool\n\nTypeScript:\n\n```bash\nnpm install sello\n```\n\n```ts\nimport { sello } from \"sello\";\n\nconst receipts = sello.service();\n\nexport const createEvent = receipts.tool(\"calendar.create_event\", async (request) =\u003e {\n  return calendar.events.create(request);\n});\n```\n\nPython:\n\n```bash\npip install sello\n```\n\n```py\nimport sello\n\nreceipts = sello.service()\n\n@receipts.tool(\"calendar.create_event\")\ndef create_event(request):\n    return calendar.events.create(request)\n```\n\nIn local dev, `npx sello dev` supplies the config this snippet needs. In production, configure your service with a service id, service signing key, token issuer, and log URL:\n\n```bash\nSELLO_SERVICE_ID=calendar.example.com/mcp/v1\nSELLO_SERVICE_KEY=sello_live_local_...\nSELLO_TOKEN_ISSUER_JWKS=https://auth.example.com/.well-known/jwks.json\nSELLO_LOG_URL=https://logs.example.com/api\nSELLO_SUBMIT_MODE=background\n```\n\nSello works with your own log server. Using `sello.build` is an optional convenience, not a protocol requirement.\n\nTo scaffold a tiny emitter or HTTP route:\n\n```bash\nnpx --yes sello init-demo\nnpx --yes sello init-http-demo\n```\n\n## Add Sello to an MCP Server\n\nIf your service exposes MCP tools, wrap the tool callback:\n\n```ts\nimport { sello } from \"sello\";\n\nconst receipts = sello.service();\n\nserver.registerTool(\n  \"calendar.create_event\",\n  { inputSchema: createEventInputSchema },\n  receipts.mcpTool(\"calendar.create_event\", async (args) =\u003e {\n    const event = await calendar.events.create(args);\n    return {\n      content: [{ type: \"text\", text: event.id }],\n    };\n  }),\n);\n```\n\nSome MCP SDK versions call this method `tool` instead of `registerTool`; use the same callback slot either way.\n\n`mcpTool` verifies the agent token before your callback runs, preserves the callback's return value, rethrows callback errors, and emits a receipt with action type `mcp.tools/call.\u003ctool-name\u003e`.\n\nBy default, Sello looks for an `Authorization: Bearer ...` token in common MCP context/header fields. If your transport stores tokens somewhere else, pass an extractor:\n\n```ts\nreceipts.mcpTool(\"calendar.create_event\", handler, {\n  authorizationToken: ({ context }) =\u003e context.session.token,\n});\n```\n\nSee [docs/mcp.md](docs/mcp.md) for token handling, hash boundaries, unknown-tool behavior, and action viewing.\n\n## See Logged Actions\n\n```bash\nnpx sello actions\n```\n\nIn local dev, `sello actions` reads the latest dev token and owner key from `.sello/dev.json`. To inspect actions for a specific agent token, pass it explicitly:\n\n```bash\nnpx sello actions --token \u003cagent-token\u003e\n```\n\nThe token is the same authorization token the agent used when it called services. Sello hashes the exact token bytes into `sello_token_ref`, queries trusted logs, verifies matching receipts, and decrypts them with the owner key.\n\nPublic logs store encrypted receipts. Viewing action details requires the owner private key or an explicitly delegated viewer key.\n\n## How It Works\n\nMost agent logs are written by the same system whose behavior they describe. If the agent, runtime, or operator is compromised, those logs can be incomplete or false.\n\nSello moves receipt-writing to the services the agent calls. The service was present for the action, but it is outside the agent's own logging path.\n\n1. The agent calls a service with an authorization token.\n2. The service verifies the token, runs the action, and signs an encrypted receipt for what it observed.\n3. A transparency log stores the encrypted receipt.\n4. The owner later fetches, verifies, and decrypts the receipt.\n\nSello helps an owner verify that a specific service signed a specific receipt, the receipt was encrypted for the owner, the receipt was included in a trusted transparency log, and the receipt body was not modified after signing.\n\nSello does not prove that the agent called every service it should have called, that every service is honest, or that unauthenticated log indexes returned complete results. Those limits are intentional and documented in the spec.\n\n## Learn More\n\n- [SDK Quickstart](docs/sdk-quickstart.md): local dev, HTTP demo, self-hosted config, and hosted config.\n- [MCP Integration](docs/mcp.md): where Sello wraps MCP tool callbacks.\n- [SDKs](sdks/README.md): TypeScript and Python package layout.\n- [Python SDK](sdks/python/README.md): Python package install command, scope, and test command.\n- [Protocol Walkthrough](docs/protocol-walkthrough.md): the primitive receipt loop for implementers.\n- [SPEC.md](SPEC.md): the Sello protocol draft.\n- [Notarized Agents paper](https://arxiv.org/abs/2606.04193): design rationale, threat model, and prior art.\n- [sdks/typescript/examples/mcp-minimal-server.ts](sdks/typescript/examples/mcp-minimal-server.ts): a small MCP integration.\n- [docs/security-review.md](docs/security-review.md) and [docs/sdk-security-audit.md](docs/sdk-security-audit.md): current review notes.\n\nThe TypeScript SDK is published on [npm](https://www.npmjs.com/package/sello) and lives in [`sdks/typescript/`](sdks/typescript/). The Python SDK is published on [PyPI](https://pypi.org/project/sello/) and lives in [`sdks/python/`](sdks/python/). Both SDKs support the same service-side `sello.service()` flow; Python uses the `@receipts.tool(...)` decorator. Live Rekor proof verification and production identity operations are still future work.\n\n## Core Terms\n\n- **Owner:** deploys the agent and holds the HPKE private key.\n- **Agent:** calls services with authorization tokens.\n- **Service:** signs receipts for actions it observed.\n- **Receipt:** encrypted CBOR body inside a signed COSE_Sign1 envelope.\n- **Transparency log:** append-only store that returns inclusion proofs.\n- **`sello_token_ref`:** SHA-256 of the exact raw compact JWS bytes.\n- **`sello_log_url`:** canonical URL of the log that stored the receipt.\n\n## Related Work\n\nVerifiable records of agent activity are an active area, and several projects are working nearby. Sello's specific combination, where the receiving service signs the receipt, encrypts it to the owner, and publishes it to a public transparency log, appears to be distinct, but the surrounding space is rich and worth knowing.\n\nClosest neighbors include Signet, which co-signs MCP responses but keeps receipts in operator-controlled storage; AgentROA, which publishes per-action receipts to a SCITT log but signs at an operator-side gateway and in cleartext; Agent Receipts, which signs on the agent-platform side; and the IETF SCITT working group, whose COSE_Sign1 transparency-receipt framework Sello builds on. Each gets one or two of Sello's four properties. None, as far as we found, combines all four.\n\nMuch of this prior work surfaced after Sello's design had already converged on similar primitives. That independent convergence is a good sign the problem is real. See [SPEC.md](SPEC.md) §12 for the fuller prior-art discussion.\n\n## Sharp Edges\n\n- Hash the exact raw compact JWS bytes. Do not parse and reserialize first.\n- Compare log identities by canonical URL string; see `SPEC.md` §6.2.\n- Do not treat an unauthenticated Rekor/off-log index as proof of completeness.\n- Use verifiable log integrated time for revocation decisions, not the receipt timestamp.\n- Deduplicate only on the full spec key, including action type and input/output hashes.\n\n## Feedback\n\nIssues and pull requests are welcome. This is an early draft; adversarial review is the point. See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution notes and [SECURITY.md](SECURITY.md) for sensitive reports.\n\n## License\n\nApache 2.0. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuanfiguera%2Fsello","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuanfiguera%2Fsello","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuanfiguera%2Fsello/lists"}