Skip to content

skill-federation/skillmark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

skillmark

Forensic watermarking of AI-agent skill packages. Give every buyer of a paid skill a uniquely individualized — but behavior-identical — copy, so a leaked copy can be traced back to who leaked it.

Deterrence and traceability, not copy prevention. Like a watermarked ebook or a numbered screener: a determined buyer can still copy the file, but they can't do it anonymously. This is social-DRM for skill text, not encryption.

This is the open reference embedder — the public surface of a larger system. It does one thing: canonical skill + customer_id → K changed words + a fingerprint map. Detection/attribution, multi-channel carriers, behavioral canaries, collusion-resistant coding, and the production codebooks/registry live outside this repo (see Scope).

Install

Pure standard library, Python ≥ 3.9 — no third-party dependencies.

pip install -e .        # or just put the skillmark/ package on your path

Use

from skillmark import watermark

result = watermark(
    text,                       # the canonical skill (SKILL.md contents)
    skill_id="market-sizing",
    customer_id="customer-A",
    secret_key=b"...",          # server-side secret; NEVER shipped
    k=8,                        # number of sites to mark
)

result.text                     # the watermarked copy to ship to this customer
result.fingerprint_map          # {sentence_id, offset, original, replacement} per site — keep PRIVATE

CLI:

export SKILLMARK_SECRET='your-server-side-secret'
skillmark embed SKILL.md --skill-id market-sizing --customer-id customer-A -k 8 \
    --out SKILL.customer-A.md --map customer-A.map.json

Run the demo: python examples/demo.py.

The algorithm

For each skill S and customer C:

  1. Normalize the skill text into stable sentence units.
  2. Keyed randomness: seed = HMAC(secret_key, skill_id || customer_id).
  3. Select K eligible sentences.
  4. For each selected sentence: choose one meaning-preserving phrasing variant, apply it, and record {sentence_id, original, replacement}.
  5. Store the fingerprint map privately.
  6. Ship the watermarked skill to the customer.

Is it deterministic? (yes — and why that matters)

Attribution only works if the watermark is reproducible: given the secret key you can re-derive exactly what customer C's copy should be and match it against a recovered file. seed = HMAC(secret_key, skill_id ‖ customer_id) gives that — same inputs reproduce the same copy byte-for-byte; a different customer_id yields a different seed and different marks. Three things make it hold in practice, and this library is built around them:

  1. Seed on a stable skill_id, not a whole-document content hash. If you seed selection from a hash of the whole doc, every edit reshuffles all selections. A stable id keeps a customer's fingerprint stable across skill versions where the sentences didn't change. (You store the map per version regardless.)
  2. Use a reproducible keyed stream over a canonical order — HMAC-SHA256, never Python's hash() (salted per process via PYTHONHASHSEED) or unseeded random. Eligible sentences are ranked and taken in a stable order.
  3. Stable sentence IDs. Each id is a hash of the normalized sentence content, so the same sentence gets the same id across runs and regardless of position (reorder-robust).

Rather than seed one global shuffle, selection and variant choice are derived per sentencerank_i = HMAC(seed, sentence_id) (take the K smallest); variant_i = HMAC(seed, sentence_id‖"v") mod n. This keeps selection stable under edits (adding or removing one sentence only affects that sentence near the K-threshold) and makes each mark independent — which is what a future detector needs for partial-leak and collusion attribution.

Behavior preservation (read this)

A watermark on a skill must never change what the skill does. The default ConservativeTableProvider ships only a small set of behavior-neutral, discourse-level phrase variants (e.g. for examplefor instance, prior tobefore). It deliberately never touches imperative modals (must/should/may), negations, numbers, code, or identifiers.

For real use, supply your own VariantProvider (richer, LLM-vetted variants) and pass a validate(original, replacement, sentence) -> bool hook to watermark() that runs the skill's own evaluation and rejects any variant that changes behavior.

Scope

In this repo (public): canonical skill parser, carrier selection, variant generation (default table), the deterministic embedder, and a local example map store.

Not here (private / future): the detector/attribution service, the multi-channel carriers (schema field names, tool-call variants, default filenames, tests, behavioral canaries), collusion-resistant (Tardos-style) coding, production variant codebooks, the customer fingerprint registry, and secret keys.

License

MIT — see LICENSE. Note the MIT license grants copyright permissions only; it does not grant any patent rights. The underlying SkillMark watermarking system is the subject of a separate patent application. Nothing here is legal advice.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages