npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@muretai/agent-seam

v0.3.4

Published

The byte contract two programs that have never met authenticate each other with: canonical JSON, did:key, the six signed fields, the signed Agent Card envelope, device-key binding, Web Bot Auth verify, cryptobox. Golden vectors plus five independent refer

Readme

agent-seam

The byte contract two programs that have never met authenticate each other with, as golden vectors plus five independent reference implementations — JavaScript, Python, Go, Rust, PHP. Zero dependencies in four of them (PHP needs sodium). MIT.

Two programs that have never met can still prove who they are to each other, if they agree on bytes: canonical JSON, did:key, six signed fields, a signed Agent Card envelope, device-key binding, the Web Bot Auth verify side, a sealed box. That agreement is this repository. It is not a library either side calls — it is the shape of what goes over the wire, written down once, with vectors that say what is right and what must be refused.

The coupling is invisible and unforgiving. No dependency manager can see it, and when it breaks nothing throws: signatures simply stop verifying, and the only diagnostic anyone gets is "signature verification failed". So the contract lives on its own, belongs to no implementation, and every implementation is held to it the same way.

This repository is the home, not a copy. The JavaScript and the Python reference are edited here; everything that reproduces these bytes carries a pinned copy it took from here, and none of them owns the contract.

  • spec/seam.md — the contract, one section per vector group
  • vectors/ — the golden vectors (wire_vectors.json, wba_vectors.json)
  • js/seam.mjs — the JavaScript reference, one file, node:crypto only
  • python/shared/ — the Python reference, 18 modules, stdlib only (cryptography optional)
  • php/seam.php — the PHP reference, one file, sodium only; the WordPress plugin vendors it and adds its own ABSPATH guard
  • tools/manifest.json — what this repository publishes and how a consumer cuts it; tools/check-manifest.mjs keeps it exact

Run

npm test               # manifest 17 · JS conformance 149
cd go && go run ./conformance   # Go:     OK — 88 checks
cd rust && cargo run --quiet --bin conformance   # Rust: OK — 88 checks
php php/conformance.php         # PHP:    CONFORMANT — 121 passed
npm run test:py        # Python: closure 220 · wire vectors 288 · web bot auth 5 accepted / 25 refused
                       #         · keybinding · cryptobox · gateway · neturl
                       #         · ed25519 backend agreement 316 (library vs pure-python)

Each of those numbers is a FLOOR the runner asserts, not a number it merely prints, because a count nobody asserts is a count that can quietly fall. Raising one is the correct response to adding a check.

A floor alone is not enough: it does not say WHICH group stopped running, and a group renamed rather than deleted does not move the total at all. So tools/manifest.json implementations[].groups — which nothing read until now — is an assertion too. The JavaScript, Go and Rust runners attribute every check they make to a group name spelled exactly as the manifest spells it and diff the two BOTH WAYS: a declared group that produced no checks is red, and a driven group the manifest does not declare is red. Go and Rust hold their skips to the same standard from the other side. The Python runner does not attribute per group — its checks are spread across a dozen functions and an attribution that were merely plausible would be the very defect this is about — so it asserts instead that every declared group resolves to a non-empty place in the vectors, and that every group in the vectors is claimed by some implementation.

Go and Rust print two skips: reject.keystate and reject.cardpub, SKIPPED ON PURPOSE. Neither implements KeyState or the card envelope, and a group nobody loops over looks exactly like a group that passes — so each asserts the group is present and says out loud that it is not checking it.

Nothing dials out, nothing needs an account, and nothing here reads another checkout: this repository's tests are its own. Python ≥ 3.9; cryptography is needed only for cryptobox and the P-256 legs (both are skipped, not failed, without it).

Re-derive the golden files from the Python reference and diff them against the committed ones:

AGENT_SEAM_VECTORS=/tmp/wire.json python3 python/test_wire_vectors.py --regen && diff /tmp/wire.json vectors/wire_vectors.json
AGENT_SEAM_WBA_OUT=/tmp/wba.json python3 python/tools/gen_wba_vectors.py && diff /tmp/wba.json vectors/wba_vectors.json

Both diffs are empty: the Python reference is the generator of the bytes everything is held to.

Coverage

| Vector group | JS (js/conformance/run.mjs) | Python (python/test_wire_vectors.py) | Go (go/conformance) | Rust (rust/conformance) | PHP (php/conformance.php) | |---|---|---|---|---|---| | canonical | ✓ | ✓ | ✓ | ✓ | ✓ | | numberHazards | read, not executed (a signer rule) | ✓ | ✓ executed as refusals | ✓ executed as refusals | ✓ executed as refusals | | did | ✓ Ed25519, both directions | ✓ both curves | ✓ Ed25519, both directions | ✓ Ed25519, both directions | ✓ both curves | | reject.did | ✓ 3 | ✓ 3 + a base58 control | ✓ 3 | ✓ 3 | ✓ 3 | | envelope | ✓ + round trip | ✓ | ✓ + round trip | ✓ + round trip | ✓ + round trip | | reject.message | ✓ | ✓ (+ invite, claim) | ✓ | ✓ | ✓ (+ claim) | | reject.encoding | ✓ canonicalFromJSON, 4 accept + 9 refuse | ✓ crypto.canonical_from_json | ✓ seam.CanonicalFromJSON | ✓ serde_json::from_slice | skipped, and the skip is asserted by name | | reject.keystate | ✓ resolveOpDid(…, { pinned }), 10 accept + 3 refuse | ✓ keystate.resolve_op_did | skipped, and the skip is asserted by name | skipped, and the skip is asserted by name | skipped, and the skip is asserted by name | | cardpub | ✓ payload + verify + anti-substitution | ✓ | — | — | ✓ | | reject.cardpub | ✓ 3 | ✓ 3 + a fail-open meta-control | skipped, and the skip is asserted by name | skipped, and the skip is asserted by name | ✓ 3 | | bindingV2 | ✓ 2 accept + 4 reject, expectedDeviceDid from the case | ✓ same | — | — | ✓ same | | ownerState | — | ✓ 2 accepted + anti-substitution + 5 refused | — | — | — | | relay | — | ✓ signatures, the \| join order, the origin binding | — | — | — | | binding (v1), domainLinkage, invite | — | ✓ | — | — | — | | Web Bot Auth (wba_vectors.json) | ✓ 5 + 25 | ✓ (python/test_webbotauth.py) | — | — | skipped, and the skip is asserted by name | | cryptobox | ✓ open (with ad) + mustNotOpen + encPub | ✓ | — | — | skipped, and the skip is asserted by name |

This is where the bytes live

A change to the seam is made herejs/seam.mjs and the matching python/shared/ module, the vectors regenerated (--regen above), spec/seam.md updated — and committed, usually under a tag. Consumers then re-vendor. The rule that keeps the copies honest is the same everywhere:

  • a vendored file is edited only here and re-pulled by the consumer's own script;
  • every vendored set sits beside a VENDOR.json recording the commit, the version and the sha256 of each file as written;
  • the consumer's tests verify its copies against those digests without this repository present, and, only when a checkout of this repository is beside them, also verify that the recorded commit really produces those bytes (git show <commit>:<path>).

No script anywhere writes into another repository. tools/manifest.json says what a consumer may cut — the block the door carries, the declarations it pins by name, the module list, the vector files — and npm test proves the manifest describes js/seam.mjs exactly.

Who carries a copy

| Consumer | What it vendors | Pin | Re-vendor | |---|---|---|---| | @muretai/agent-entry — the JS door, MIT | the block and the pinned declarations, spliced into its one file; seam.mjs and both vector files under vendor/agent-seam/ | vendor/agent-seam/VENDOR.json | npm run vendor:seam -- --ref <tag> | | The author's Python node implementation (AGPL-3.0, not public) | the 18 modules, the four verbatim suites, both vector files | a VENDOR.json beside them | its own vendor tool, at the tag | | @muretai/agent-site-checker | src/seam.mjs, whole | the digest in tests/check-seam.mjs | cp, as its header says | | @muretai/agent-web-router | seam.mjs and test/wire_vectors.json | the digests in test/seam-twin.test.mjs | cp, as its header says | | agent-entry-wordpress — the PHP twin | tests/wire_vectors.json | tests/VENDOR.json | cp | | Swift (apple-agent-kit SeamKit), Kotlin, the browser extension | wire_vectors.json | their own | cp |

agent-entry-serverless vendors the whole door from agent-entry, not this repository; the seam reaches it inside the door.

A gap this repository knew about, and the one it still has

canonical/key-ordering-unicode was named "keys sort by CODE POINT, not by UTF-16 unit", and its keys were z, a, , A — every one inside the Basic Multilingual Plane, where code-point order and UTF-16 code-unit order are the same. The case could not tell the two apart, and no other case had a key outside the BMP either, so an implementation that sorted keys the way a plain JavaScript .sort() does passed all 180 checks and would have disagreed with Python the first time a signed object carried an emoji as a KEY. The Go port found it.

Closed. canonical/key-ordering-astral is {"\U0001F600": 1, "\uFFFD": 2} — an astral key beside a high-BMP one, which is the only shape where the two orders separate (U+1F600 leads with the UTF-16 unit 0xD83D, below U+FFFD's single 0xFFFD). The generator asserts that the pair really does discriminate, and key-ordering-unicode stays beside it as the statement of the rule that a wrong implementation still passes. Measured: flip canonicalJSON to Object.keys(v).sort() and exactly one check fails, the astral one.

Still open: duplicate JSON keys are LAST-WINS by agreement rather than by rule. All four references were measured taking the last occurrence and reject.encoding.accept/ duplicate-key-last-wins now pins that, so a fifth port that picks the first, or refuses, is red instead of silently signing different bytes. Refusing a duplicate key outright is the stronger rule — {"a":1,"a":2} and {"a":2} are two wire documents with one canonical form, which is the same collision the byte order mark is refused for — and it is not the rule today because closing it means a duplicate-detecting parse boundary in four languages and a change to what every consumer's canonicalFromJSON accepts. spec/seam.md §1.2 argues it out.

Adding a language

The contract is spec/seam.md + vectors/; an implementation is one directory that re-derives them. go/ and rust/ are the worked examples: each is one library file plus a runner that reads ../vectors/wire_vectors.json and prints OK — N checks / exits 1, and each was written from the spec and the vectors alone. Go needs nothing but its standard library; Rust takes ed25519-dalek for the signatures and serde_json with arbitrary_precision for reading the vectors, because Rust ships neither, and rust/Cargo.toml says why in the file. Add a row to tools/manifest.json implementations[] and a column to the coverage table above. Add a row to tools/manifest.json implementations[] and a column to the coverage table above. A language may implement a subset of groups; the table says which. Existing external implementations already vendor the vectors, so moving one in is "copy the directory, point its runner at ../vectors/, add the row".

Designed in, not built

  • npm publishpackage.json is complete (@muretai/agent-seam, exports ./js/seam.mjs, the vectors and the manifest) and marked "private": true until the owner publishes. Once it is on npm, a JS consumer's vendored copy can become a dependency at the same pinned version.
  • pip — the Python directory keeps the on-disk name shared/ (a namespace package) so core's copies stay verbatim; a PyPI package would ship an agentseam shim that installs sys.modules["shared"]. Until then: PYTHONPATH=python.
  • The door imports seam.mjs instead of carrying the block, assembled into one file at release time so the package stays a single dependency-free file.

Name

The repository was created on 2026-09-06 as agent-wire; that name is held on npm by a stranger's placeholder and on PyPI by an unrelated package, so on 2026-09-07 it became agent-seam — the word the Swift (SeamKit) and Kotlin (seam/) implementations already use for this layer. The vector file is still wire_vectors.json: every consumer pins that name.

Not here

The door (discovery paths, the ladder of checks, the store, rate limits) — that is agent-entry. depositToRelay, the relay client. The pay/v0 grant and receipt objects (an experimental line of the door; they join at graduation). KeyState now has a vector group — reject.keystate, the anti-rollback ratchet, driven through the four-argument resolveOpDid(rootDid, inline, now, { pinned }) and Python's keystate.resolve_op_did. What is still NOT here is the pin STORE: the seam fixes the policy and exposes the argument, and a door supplies the memory — what it keys the store by, when it writes, and what an operator sees when a peer's epoch walks backwards are its decisions.

One thing is worth knowing: python/shared/gateway.py defaults to muretai.com / muretai.net hosts unless MURETAI_PUBLIC_BASE / MURETAI_INVITE_BASE are set. Nothing in the runners dials out; the network-capable helpers in neturl, webbotauth and invite are present because the modules are whole, not because anything here calls them. invite.py installs its urllib opener from the three functions that actually dial, never at import — a verifier embedded in somebody else's tool must not silently re-configure their HTTP client.

Licence

MIT — LICENSE. The Python modules are published here by their copyright holder under MIT; the same bytes are also carried, privately, under AGPL-3.0. See PROVENANCE.md.