@agenticprimitives/registry-kit
v0.0.0-alpha.1
Published
AP-native registry-building primitives: Smart-Agent-anchored registry entries, signed-card binding proofs, claim-slot schemas, lifecycle call builders, and event decoders for vertical registries. External registry publication/sync stays outside Ring 0.
Maintainers
Readme
@agenticprimitives/registry-kit
AP-native registry-building primitives — Smart-Agent-anchored registry entries, signed-card binding proofs, claim-slot schemas, lifecycle call builders, and event decoders for vertical registries.
Status: experimental (0.0.0-alpha). Spec: specs/279-agent-discovery-registry-kit.md.
Why
The "many-registries hypothesis" (ADR-0038): hundreds of (mostly vertical) agent registries will exist; there is no horizontal winner. So Ring 0 ships the kit registries are built FROM, not another registry to join. The Smart Agent address is the canonical identifier (ADR-0010); a registry entry, a signed agent card, and any external listing are facets that point at it.
This package's one job: let a verifier confirm a registry entry is a genuine facet of a specific Smart
Agent and a specific signed card — without trusting the registry that served it — and give registry
authors generic claim-slot schemas, lifecycle call builders, and event decoders. It does not query
directories, rank or match agents, own intent, or speak an external registry protocol; those live in
identity-directory, the intent packages, apps, or external integration repos.
Install
pnpm add @agenticprimitives/registry-kit @agenticprimitives/types viemBinding proof
A binding proof is a deterministic sha256 over the proof body
(registryId, entryId, subjectAgent, cardHash, claimHashes, issuedAt), signed by the subject
Smart Agent via ERC-1271. Both the signer and the on-chain ERC-1271 read are injected, so the
package stays a pure, network-free leaf.
import { buildEntryBindingProof, verifyEntryBindingProof } from '@agenticprimitives/registry-kit';
// build — `sign` is your SA's ERC-1271-validatable signer over the 32-byte digest
const proof = await buildEntryBindingProof(
{
registryId: 'urn:ap:registry:health-eu',
entryId: 'urn:ap:registry-entry:abc',
subjectAgent: '0xSmartAgent…',
cardHash: 'sha256:…', // hash of the agent-profile signed card bundle
claimHashes: ['sha256:…'], // hashes of the claims that fill the registry's slots
issuedAt: new Date().toISOString(),
},
sign,
);
// verify — `verifier.verifyHash` is satisfied structurally by a viem PublicClient
const result = await verifyEntryBindingProof(proof, { verifier });
if (result.ok) {
// result.subjectAgent / result.cardHash / result.claimHashes are trustworthy
}verifyEntryBindingProof is fail-closed (ADR-0013):
it recomputes proofHash from the proof's own fields (catching any field tamper that left the hash
stale) and re-checks the subject SA's ERC-1271 signature over that digest (catching a tamper that
also rewrote proofHash, since the signature committed to the original digest). Any anomaly returns
{ ok: false, reason } where reason ∈ { bad_shape, proof_hash_mismatch, signature_invalid }. There is
exactly one verification mechanism — no escalation to a second, weaker path.
Lifecycle call builders
Pure encoders that return the { to, value, data } a Smart Agent executes via its own custody / UserOp
path. registry-kit never sends transactions and never decides who may call — the contract's pluggable
membership / validation hook owns authorization.
import { buildRegisterEntryCall, buildRevokeEntryCall } from '@agenticprimitives/registry-kit';
const register = buildRegisterEntryCall({
registry: '0xAgentRegistryBase…',
registryId: 'urn:ap:registry:health-eu',
entryId: 'urn:ap:registry-entry:abc',
subjectAgent: '0xSmartAgent…',
cardHash: 'sha256:…',
bindingProofHash: 'sha256:…',
claimHashes: ['sha256:…'],
expiresAt: 0, // unix seconds; 0 = non-expiring
});
// → submit `register` through your SA execution pathURN ids (urn:ap:registry:…, urn:ap:registry-entry:…, urn:ap:registry-claim-slot:…) become their
on-chain bytes32 keys via keccak; sha256:<hex> content hashes become bytes32 (the raw 32 bytes).
Helpers urnToBytes32 / sha256ToBytes32 / reasonToBytes32 are exported. The Solidity
AgentRegistryBase peer (spec §4) lands in @agenticprimitives/contracts in a later increment and must
match AGENT_REGISTRY_BASE_ABI.
Event decoding
import { decodeRegistryKitEvent } from '@agenticprimitives/registry-kit';
const event = decodeRegistryKitEvent({ topics, data }); // one raw log → typed RegistryKitEventThe decoder is for an indexer to project events into an A-box read model (adding block / tx / log provenance itself). Product discovery reads query that read model, never chain logs (ADR-0012). The A-box is treated as evidence and discovery substrate, never as authority — and never holds private vault bodies, private delegations, or raw PII.
Boundaries
registry-kit is a generic Ring-0 primitive. It depends only on @agenticprimitives/types and viem,
and is forbidden from importing identity-directory, the intent packages, fulfillment, mcp-runtime,
or any app. Signed-card bundles belong to agent-profile; graph/read-model query to
identity-directory; GraphDB / indexer / discovery UI to apps or external integration repos
(ADR-0037).
ERC-8004 / HCS / OASF vocabularies are mappings and design inputs (see packages/ontology/mappings/),
never AP package semantics.
License
MIT
