Specification / DID Method

did:oas

The DID method for autonomous agents. Every identifier is derived from a public key, making the DID itself a cryptographic commitment.

did:oas:l1fe:agent:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
five segments, decoded below
01Scheme
did

W3C Decentralized Identifier scheme. Always the literal string 'did'. The universal prefix that signals this URI follows the DID specification.

02Method
oas

Open Agent Specification method identifier. Declares that this DID conforms to OAS resolution rules, cryptographic requirements, and entity kind taxonomy.

03Namespace
l1fe

Issuing authority or network scope. DNS-label-safe string (1-63 chars). Enables multi-tenant resolution without collision. Examples: 'l1fe', 'acme', 'self'.

04Entity Kind
agent

One of 12 typed identifiers: hmr, mhr, enr, ao, agent, agent:instance, tool, skill, workflow, model, dataset, service. Determines lineage requirements and capabilities.

05Identifier
z6MkhaXgBZDv...ta2doK

Base58btc-encoded multibase representation of the entity's Ed25519 public key. Self-certifying: the identifier IS the cryptographic key. The 'z' prefix signals base58btc encoding.

Method Properties

Self-certifying

The identifier is derived from the public key, so possession of the key proves control of the DID — no registry required to establish ownership.

Offline-verifiable

Document signatures and fully bound lineage proofs verify from bundled evidence via typed authorizing APIs. Privileged authority still requires verifier trust anchors and fail-closed freshness policy.

Typed by design

The kind segment types every identity at the URI level, so policy engines can reason about what an entity is before resolving anything.

CRUD Operations

Lifecycle of a DID

CREATELocal
const hmr = await createHmr("l1fe", "alice", now);
hmr.document.id // "did:oas:l1fe:hmr:alice"
hmr.document.kind // "hmr"
hmr.document.sequence // 0
hmr.document.proof?.type // "Ed25519Signature2020"

createHmr from @openagentid/oas-sdk generates an Ed25519 keypair, constructs the DID, and signs the initial document via DocumentBuilder — verification method, conformance level, lifecycle status, sequence 0.

Document signatures verify from bundled evidence; privileged authority still needs trust anchors.

READResolve
const doc = await resolver.resolve(did);
doc.kind // "agent"
doc.conformanceLevel // "L1"
await verifyDocumentProof(documentWithoutProof(doc), doc.proof, publicKey);
// true — signature valid, document integrity confirmed

Any Resolver returns the signed document for a DID — InMemoryResolver for tests, CachingResolver and FallbackResolver for production stacks. Integrity verifies from the public key alone.

Supports offline verification when the document is bundled.

UPDATESigned Re-issue
const next = await new DocumentBuilder(doc.id, doc.kind)
.controller(doc.controller)
.addVerificationMethod(keypair)
.addService({ id: `${doc.id}#api`, type: "AgentApi", serviceEndpoint })
.conformanceLevel(ConformanceLevel.L1)
.sequence(doc.sequence + 1) // monotonic: 2 → 3
.buildAndSign(keypair, now);

Updates re-issue the document: rebuild it with DocumentBuilder, bump the monotonic sequence, and sign again with the controlling key. Earlier sequences remain verifiable for historical checks.

Sequence numbers only move forward — stale documents are detectable.

DEACTIVATERevocation
const { revoked } = await authority.checkRevocation(did);
revoked // true
doc.revoked // true — the in-band marker
doc.revokedAt // "2026-08-01T00:00:00Z"
isRevoked(doc) // true — verifiers fail closed

Revocation is marked in-band: the document carries revoked and revokedAt, authority backends report it via checkRevocation, and lineage verification rejects any chain that contains a revoked entity.

Revocation is irreversible. Key rotation is preferred.