Innsegl

Verifiable identity and attribution for AI agents.

Innsegl issues a single-purpose cryptographic identity to each agent run, attributes every action and every commit to that identity, and records the attribution somewhere a third party can check it without trusting the system that produced it — including without trusting whoever operates that system.

Innsegl is Norwegian, from Old Norse innsigli: the seal pressed on a document to prove who issued it.

Status: pre-1.0, and several things below are not built

This is an in-progress open-source project, not a product. The honest inventory, as of this page:

  • Nothing is released. There is no tagged version, so @latest resolves to a pseudo-version of the default branch. Every interface that is not named as protected below can still change without notice.
  • Nothing is hosted. innsegl.dev serves this page and the Go module path. The public verification page and the operator dashboard are written but are not deployed at any address, and there is no instance of the server you can point an agent at.
  • There is no public Go API. Every package except cmd/innsegl is under internal/, so the module is a program rather than a library. Do not plan to import it.
  • innsegl seal is listed in the CLI's help and exits non-zero. Segment sealing and Rekor anchoring exist as code; the subcommand an operator would schedule does not yet.
  • The end-to-end claim is not yet demonstrable by you. The signing and anchoring paths are exercised against real SPIRE and a real Fulcio and Rekor in this project's own test containers. That is not the same as a deployment you can run and check, and it should not be read as one.

If something on this page is not a command you can run yourself, read it as a design intention rather than a shipped feature.

What it is

Agent work is unattributed. Nobody can prove which agent did what, and nothing stops an operator from disputing the attribution afterwards. Innsegl is one identity service and one append-only ledger, arranged so that issuance is centralized and verification is not.

What it proves, and what it does not

Verification is three checks, against public infrastructure only:

  1. the signing certificate chains to Fulcio;
  2. the commit's entry is provably included in Rekor;
  3. the identity claimed in the commit trailer is the identity in that certificate.

All three run against git, Fulcio and Rekor. None of them reads this system's database — the verifier has no flag with which to point it at one, deliberately. A verification you can only perform by asking the operator's server is not a verification.

Limits worth knowing before you adopt it

Install

go install innsegl.dev/innsegl/cmd/innsegl@latest

innsegl.dev/innsegl is the module path; the code is at github.com/Raymalian/innsegl. With no tag published yet, @latest gives you a pseudo-version of the default branch — pin a commit if you need the same bytes twice.

Verify a commit, with no Innsegl deployment at all

innsegl verify <commit> -repo .

The exit status is the verdict, so it composes into a script without parsing anything: 0 verified, 3 failed, 4 verification unavailable, 5 the commit makes no attribution claim, 6 unusable — no such commit, or a configuration that cannot verify. 4 is never collapsed into 3: we could not check is a different answer from it does not hold.

Run the reference stack

The repository carries a Docker Compose stack — SPIRE, Postgres, object storage, a self-hosted Sigstore, and the server itself — under deploy/compose/. Read its README there; it is the part of this project that changes fastest.

Two names that look alike and are not

innsegl.dev/innsegl
The Go module path. It is a real URL and it resolves: this domain serves the go-import meta tag that sends the toolchain to the repository. See the tag.
spiffe://innsegl.dev
The reference trust domain — and it is not an endpoint. It has no DNS record, nothing listens on it, and nothing ever connects to it. A SPIFFE trust domain is a name: it identifies which root a spiffe://innsegl.dev/agent/… identity belongs to. Owning the matching DNS name is worth doing only because it guarantees no one else can create ambiguity about that root.

What is frozen already

Some surfaces are protected from the first release onward, because changing them retroactively would invalidate proofs that were already made: the event schema field names and enum values, the canonical serialization of an event, the commit trailer keys, the SPIFFE ID grammar, and the MCP tool names and error classes. Those change only in a major release, with a migration attestation. Everything else on this page is pre-1.0 and may move.