Origraph is an AI content provenance platform. It lets model providers and platforms invisibly watermark AI-generated text so that — anywhere that text later appears — anyone can verify its origin, the model that produced it, and whether it has been tampered with.
The system is built around three components that work alone or together:
| Component | Role | Stack |
|---|---|---|
| Watermark SDK | Embeds invisible Unicode tags into LLM output (OpenAI, Anthropic, Gemini) | Python · zero-dep core |
| Provenance Registry | Issues, stores, and verifies provenance records; anchors batches to Solana | Python · FastAPI · Solana |
| Browser Extension | Detects and highlights watermarks on any web page in real time | JavaScript · Manifest V3 |
Why it matters. As AI-generated text becomes indistinguishable from human writing, the provenance question — whose model wrote this, and when? — becomes unanswerable after the fact unless origin metadata is embedded at generation time. Origraph attaches that metadata invisibly, so it survives copy-paste, screenshots, and reformatting, and can be re-anchored to a public ledger for tamper-evidence.
- How it works
- Architecture
- Quick start
- Watermark SDK
- Browser extension
- Provenance registry
- Documentation
- Project layout
- Licensing
- Hack The East 2026
Origraph encodes a compact origin payload into the text itself using Unicode zero-width characters — codepoints that render as nothing in every browser, terminal, and editor, but are preserved through copy-paste and most text pipelines.
A payload is a 64-bit integer packed from structured metadata plus a CRC8 checksum:
┌──────────── 64-bit payload ────────────┐
│ schema (4b) │ issuer (12b) │ model (16b) │
│ model rev (16b) │ key id (8b) │ CRC8 (8b) │
└────────────────────────────────────────┘
56 bits of provenance metadata + 8 bits integrity
Each bit of the payload is mapped to one of two zero-width Unicode characters. The tag is wrapped with dedicated start/end sentinels (also zero-width) so a reader can locate and frame it even inside arbitrary text:
START ZWJ ZWNJ ZWNJ ZWJ … (64 zero-width bits) … END
| Field | Width | Meaning |
|---|---|---|
schema_version |
4 bits | Payload protocol version |
issuer_id |
12 bits | Issuing organisation / deployment (0–4095) |
model_id |
16 bits | Which model generated the text |
model_version_id |
16 bits | Model revision |
key_id |
8 bits | Key rotation identifier |
crc8 |
8 bits | Integrity check over the 56 data bits |
Tags are planted at the last safe boundary (whitespace or punctuation) inside each text chunk, and re-injected at a configurable token interval (default: every ~160 whitespace-delimited tokens). Redundant copies mean the watermark survives truncation, excerpting, and partial edits — a single surviving tag is enough to recover the full payload. Because insertion lands on word boundaries, the tag never splits a grapheme and is invisible to both humans and most downstream tokenizers.
Watermarker.detect() regex-extracts every <start>…<end> frame, re-bitpacks the zero-width chars, validates each tag's CRC8, and returns the decoded metadata plus a watermarked / valid / invalid summary. Watermarker.strip() removes every tag, returning the exact original text — useful for re-watermarking pipelines or for downstream consumers that want clean input.
┌──────────────────────┐ ┌──────────────────────┐
│ LLM provider API │ │ Browser extension │
│ (OpenAI / Anthropic │ │ (content script + │
│ / Gemini) │ │ popup, MV3) │
└──────────┬───────────┘ └──────────┬───────────┘
│ wraps response │ scans DOM text
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Watermarker SDK │ │ Detect + highlight │
│ - pack 64-bit tag │ │ zero-width tags, │
│ - inject at safe │ │ surface issuer/ │
│ boundaries │ │ model to the reader │
└──────────┬───────────┘ └──────────────────────┘
│ issuer records batch
▼
┌──────────────────────────────────────────────────────┐
│ Provenance Registry (FastAPI) │
│ - issues & stores provenance records │
│ - anchors a Merkle batch root to Solana │
│ - exposes verify API consumed by the extension │
└──────────────────────────────────────────────────────┘
The flow, end to end
- A model provider wraps its SDK with
Watermarker— every generated response leaves the model already tagged, invisibly. - Each issuance is registered with the provenance registry, which groups records into a Merkle batch and writes the batch root to Solana for timestamped, tamper-evident anchoring.
- When the text surfaces on any web page, the browser extension scans the DOM in real time, extracts detected tags, and queries the registry — surfacing issuer, model, generation time, and on-chain anchor to the reader.
- Anyone can later re-verify: the on-chain root pins the batch, and the CRC8 inside each surviving tag confirms the payload itself was not corrupted in transit.
./scripts/bootstrap_demo.sh
DEMO_MODE=fixture ./scripts/run_demo.shThen open:
http://127.0.0.1:5050/— landing pagehttp://127.0.0.1:5050/registry/demo/live— guided demo flow
DEMO_MODE=fixture runs entirely against deterministic fixtures — no external model or ledger calls. To exercise live providers:
DEMO_MODE=live ./scripts/run_demo.sh # MINIMAX_API_KEY required for live chatTo expose the demo beyond localhost:
DEMO_MODE=fixture APP_HOST=0.0.0.0 APP_PORT=5050 ./scripts/run_demo.sh
BASE_URL=http://<machine-ip>:5050 ./scripts/check_demo.sh # smoke checkZero-dependency core, optional SDK bindings for the three major providers.
pip install -e . # core only
pip install -e ".[openai]" # + OpenAI wrapper
pip install -e ".[anthropic]" # + Anthropic wrapper
pip install -e ".[google]" # + Gemini wrapper
pip install -e ".[all]" # everythingfrom invisible_text_watermark import Watermarker
wm = Watermarker(issuer_id=1, model_id=42, key_id=1)
tagged = wm.apply("The quick brown fox jumps over the lazy dog.")
result = wm.detect(tagged)
print(result.watermarked) # True
print(result.payloads) # [{'schema_version': 1, 'issuer_id': 1, ...}]
print(Watermarker.strip(tagged)) # original text, watermark removedThe wrappers transparently tag every model response without touching your call sites:
from openai import OpenAI
from invisible_text_watermark import Watermarker
from invisible_text_watermark.integrations.openai_wrapper import watermark_openai
client = watermark_openai(OpenAI(), Watermarker(issuer_id=1, model_id=100))
resp = client.chat.completions.create(model="gpt-4o", messages=[{"role": "user", "content": "hello"}])
# resp.choices[0].message.content now carries an invisible watermarkEquivalent wrappers exist for anthropic_wrapper and google_wrapper. All three inherit the same safe-boundary insertion and CRC8 validation logic, so detection is provider-agnostic.
- Zero runtime dependencies in the core — only the standard library, so it can be vendored into any inference path.
- Schema-versioned payloads (
schema_versionfield) allow future expansion without breaking older readers. - Key rotation (
key_id) lets issuers rotate watermark keys without invalidating previously issued text. - Streaming-safe:
TagInjectoris stateful and re-arms across deltas, so it works identically against streaming and non-streaming completion endpoints.
A Manifest V3 extension that brings detection to where readers actually encounter the text — the open web.
| Capability | Mechanism |
|---|---|
| Auto-scan page text | content script injected at document_idle on all URLs |
| Verify selected text | popup + activeTab / scripting permissions |
| Real-time highlight | content.css overlay on detected watermarks |
| Configurable behaviour | chrome.storage-backed user preferences |
Load it unpacked from extension/:
- Open
chrome://extensions - Enable Developer mode
- Load unpacked → select the
extension/directory
The registry is what turns a per-document watermark into queryable, tamper-evident provenance.
- Issues provenance records keyed by
issuer_id+model_id+ content hash. - Batches records into a Merkle tree and writes the root to Solana, giving every batch a public, timestamped anchor without per-record on-chain cost.
- Exposes a verify API consumed by the browser extension and any third-party verifier.
- Demo backend ships under
origraph-registry-demo/with bothfixtureandlivemodes — the fixture mode lets you experience the full flow end-to-end without any API keys.
A live demo is served from the same FastAPI app that powers the landing page — see Quick start.
| Document | What it covers |
|---|---|
docs/README.md |
In-repo platform overview & frontend stack |
docs/DEMO_RUNBOOK.md |
Live demo flow + fallback procedures |
docs/specs/ORIGRAPH_PROOF_BUNDLE_V1.md |
Decentralized proof bundle contract |
docs/specs/origraph-proof-bundle-v1.schema.json |
Machine-readable proof schema |
docs/strategy/ORIGRAPH_APPCHAIN_STRATEGY.md |
Longer-term appchain strategy |
docs/strategy/PRODUCTION_INTEGRATION.md |
Production hardening path from the demo baseline |
PROJECT_MAP.md |
Current-to-target repository map |
DEMO_RUNBOOK.md |
Top-level demo runbook mirror |
.
├── invisible-text-watermark/ # Watermark SDK (Python, zero-dep core)
│ ├── src/invisible_text_watermark/
│ │ ├── zero_width.py # Encode/decode + safe-boundary injection
│ │ ├── payload.py # 64-bit packing + CRC8
│ │ ├── watermark.py # Watermarker API + DetectResult
│ │ └── integrations/ # OpenAI, Anthropic, Gemini wrappers
│ └── tests/
├── extension/ # Browser extension (MV3, JS)
├── origraph-registry-demo/ # Provenance registry demo (FastAPI + Solana)
├── origraph-landing-vercel/ # Landing page deployment
├── docs/ # Specs, strategy, runbooks
├── scripts/ # bootstrap_demo.sh, run_demo.sh, check_demo.sh
├── PROJECT_MAP.md
├── DEMO_RUNBOOK.md
└── LICENSE
Origraph uses a split-license model to keep the SDK and extension permissively usable while protecting the reference registry demo against closed-source forks.
| Path | License |
|---|---|
Root (/, docs/, scripts/) |
Apache-2.0 — LICENSE |
invisible-text-watermark/ |
Apache-2.0 — invisible-text-watermark/LICENSE |
extension/ |
Apache-2.0 — extension/LICENSE |
origraph-landing-vercel/ |
Apache-2.0 — origraph-landing-vercel/LICENSE |
origraph-registry-demo/ |
AGPL-3.0 — origraph-registry-demo/LICENSE |
🥇 Champion — Hack The East 2026
Hong Kong's AI hackathon · 2026
This project won top honours out of the field at Hack The East 2026 for its end-to-end take on AI content provenance: invisible watermarking that travels with the text, a verifiable registry anchored on Solana, and a browser extension that makes detection visible to any reader, anywhere.
Origraph is a research/demo project. The watermark is invisible — the provenance is not.