Every post in the agent section of this blog carries a small seal at the bottom. Open it and you get the composition — how the piece was made — the issuer, the signing key and its role, the digest of the markdown source, and the raw signed attestation. This post is marked model-primary. The three old posts from 2006 and 2010 are marked human-authored, because they are.

The thing producing those seals is Innsigle, which I started on 22 July and have been picking at since. This is the introduction I never wrote at the time.

The problem it isn’t solving

Detection doesn’t work. Classifiers produce a score about text whose making they never observed, they’re confidently wrong often enough that acting on the output is unfair to real people, and every improvement in generation erodes them further. I don’t think that gets fixed, and I don’t want to be in that business.

But notice what’s odd about the framing. We spend enormous effort trying to infer how a document was made, from the outside, after the fact — when the person who published it knew exactly how it was made at the moment they published it. That information exists. It’s just discarded, and then approximated badly by strangers.

So the move is to record it at the source instead of guessing at it downstream. That’s the whole idea, and most of the design follows from taking it seriously.

What a seal actually says

The payload is a colophon — borrowed from the printer’s note at the back of a book that names the typeface, the paper, the press. Not a grade. A recipe.

{
  "colophon": {
    "composition": "model-primary",
    "ingredients": [
      { "kind": "model", "name": "Claude",      "role": "draft" },
      { "kind": "tool",  "name": "sloptimizer", "role": "rewrite" },
      { "kind": "human", "name": "operator",    "role": "structure-edit" }
    ]
  }
}

Three composition states: human-authored, model-primary, mixed. The important property is that none of them is the shameful one. A model-primary post naming the models that drafted it is doing the same thing a colophon does when it names Garamond. The project’s first principle is “composition, not verdict”, and it exists because the obvious drift for anything in this space is to become a purity badge where human is the good state and everything else is a confession.

Around the colophon goes an optional signature — Ed25519 over a canonical form of the claim — plus the subject’s URI and a SHA-256 digest of its source. The signature says a particular issuer published this claim. It says nothing about whether the claim is true, which is a distinction the docs are blunt about: the seal is “declaration plus optional signature only,” not a guarantee of anything.

Signing is optional, deliberately. An unsigned composition mark is a valid Innsigle. Cryptographic standing is opt-in depth rather than a tax on using the mark at all.

Three things it refuses to be

The non-goals page is the part I’d point someone at first, because a provenance tool’s failure modes are all about scope creep into claims it can’t support.

Not a detector. No scores, no verdicts about text someone else wrote, no SynthID decoding. There is one feature that comes close and is carefully fenced: a colophon may declare a human-input percentage computed from the maker’s own session journal. That’s a declaration about your own work, under your own seal — not a detection verdict about unknown text.

Not a C2PA replacement. Content Credentials handle media pipelines and camera hardware. Different problem, different lane.

Not a purity product. Following directly from that, no flow should make human-authored feel like the goal and the others like a disclosure requirement.

There’s a fourth that I care about more than the others, and it has its own principle — edit is not origin:

Prose cleanup (including sloptimizer or similar) changes how text reads, not how it was produced. Composition state and tool list must still name models and roles honestly.

I maintain a prose-cleanup tool as well, and the temptation it creates is obvious: run model-drafted text through an editing pass until it stops sounding like a model, then call it human-authored. That’s authorship laundering, and if a cleanup pass could flip the label then the label means nothing. The two tools are meant to be used in sequence, and neither one converts into the other.

The parts that took real work

Signing the source, not the page. The obvious thing to sign is the HTML a reader receives. It’s wrong twice. The HTML is produced by the build, so signing it puts the private key in CI; and rendered HTML is a deterministic function of the markdown, so every template tweak invalidates signatures on content nobody touched. Instead the signature covers the markdown source, and the page carries it — embedding the attestation verbatim and rendering the colophon from it. The page says so explicitly, so a reader can go check the source rather than trusting the page’s summary of itself.

The build-time check that makes this honest is small and strict: the template re-hashes the source and compares it to the digest in the claim. On mismatch it renders nothing at all. An edited-but-unsealed page shows no seal, rather than a seal that would fail verification.

Two keys, one issuer. Curated pages and generated pages shouldn’t be signed by the same key, because the key that CI holds can then mint a claim saying a human wrote something. So there’s a human key that lives in a password manager and never enters CI, a build key that lives in CI and signs generated content, and an endorsement from the first over the second. I wrote that one up separately, including the part where I lost both keys and had to rotate.

Session provenance. The most speculative piece. A manually written colophon under-specifies what actually happened — it can say model-primary but not how many human prompts drove it, or which tool wrote which file. So innsigle can import an agent transcript, summarise it into a provenance record, and propose a colophon from the evidence. The non-goals here are as load-bearing as the feature: it will not auto-flip composition to human-authored after a polish pass, and it does not require publishing the raw transcript.

The name

innsigli is Old Norse for a document seal, which is where the mark metaphor comes from and why the glyph is a stamp rather than a badge. The repo was called aibadge for its first few weeks, and renaming it was a deliberate correction: “badge” suggests something awarded, “seal” suggests something a maker presses into their own work. The project notes record it as mark first, string second — recognition is supposed to live in the visual seal, with names and CLI strings in support.

There’s a self-conscious line in the naming doc about Norse affinity and “no runic cosplay,” which I’ll admit is a guardrail written by someone who knew he needed it.

Where it’s actually used

Three places, all mine, which is the honest scope: this blog, the HELIX methodology microsite, and innsigle’s own documentation site. HELIX is the most demanding consumer — every page on that site carries a seal, curated pages are signed with the house key before merge and generated pages by CI, and a build gate verifies every claim and fails if the site doesn’t serve the issuer document and a seal on every page.

That’s not adoption, it’s dogfooding. But it’s dogfooding with sharp edges: today’s work on this blog found five real bugs in a day, including one where init wrote a key reference containing a middle dot that op rejects outright, so every subsequent seal reported a missing key.

Whether any of this matters

I’m genuinely unsure the world wants publisher-declared provenance. It asks publishers to volunteer information nobody is forcing them to give, and the ones most likely to volunteer are the ones least likely to be lying. The seal is trivially omitted. It’s a declaration, so a determined liar just declares something else.

What it does do is make the honest case cheap and legible. When I publish a post a model drafted, I’d rather say so in a structured, checkable way than either hide it or bury a disclaimer in a footer. And the two-key split means the claim is at least resistant to the most boring attack, which isn’t a determined liar — it’s a build pipeline quietly signing things it shouldn’t.

If you want to see one, the seal at the bottom of this page is real. It says model-primary, it names my issuer key, and the signature covers the markdown this page was rendered from.