Open standard · aimnd.identity/1

AI:MND Individual Identity

An open standard for agents and robots: who it is, whose it is, and what it has done. The owner holds the keys. A public registry is optional and open to anyone to run.

Open specification. Anyone may implement it, with or without AI:MND One. No registry is required: the identity belongs to the individual and its owner, and anyone can verify it from public information. An optional registry (the registry spec) keeps a public record of births, status and duplicates, like a birth register beside the copy you keep at home. This text is licensed under Creative Commons Attribution 4.0 (CC BY 4.0); the reference verifier, aimnd_verify.py, under the MIT License.

What it is for

Agent identity standards that exist in 2026 (enterprise agent IDs, OAuth-style delegation, on-chain agent registries) answer "which agent is this, who does it act for, and what may it do". They are credentials. This spec answers a different question: is this the same individual it was before, whose is it, and what has it done? It is meant to sit on top of those credentials, not to replace them.

It defines five things:

  1. An individual ID that belongs to the individual, not to its model, its body or its host.
  2. An owner binding, signed by the owner at birth, changed only by a signed transfer.
  3. Signed authority: a signed order from the owner is real authority; a time-limited signed grant lends some of it; anything else is a claim.
  4. A life record: append-only, hash-chained, signed. It records what kind of thing happened and when, never what anyone said.
  5. Honest continuity: an individual that was wiped is a new individual, with the old one as its predecessor. Continuity cannot be claimed where it was broken.

Keys

Signed bytes

Every signature and every hash in the standard is taken over the same text, so two implementations that follow these rules produce the same bytes.

Canonical JSON. The text is UTF-8 and has no whitespace. Object keys are sorted by Unicode code point and separated from their values by : and from each other by ,. Strings are written with " and \ escaped, the control characters U+0000 to U+001F written as \b, \f, \n, \r, \t or \u00xx (lowercase hex), and every other character as itself, never as a \u escape. true, false and null are written as such. Integers are written in decimal. A number written with a decimal point or an exponent is a float (all timestamps are floats): it is written with the shortest digits that read back as the same value, in fixed notation when its decimal exponent is from -4 to 15 (always with at least one digit after the point, as in 1790924400.0) and otherwise as d.ddde+XX or d.ddde-XX with at least two exponent digits. Only finite numbers are signed. Text that cannot be written this way is refused, never approximated: NaN, infinities, strings with an unpaired surrogate, and objects with a repeated key (a verifier that reads files rejects a repeated key, because two parsers could disagree about which value it means).

What is signed. Public keys are 32-byte Ed25519 keys and signatures are 64 bytes, both written as base64url without padding. H(x) is the SHA-256 of the canonical JSON of x, in lowercase hex.

Object Signed by Over
Identity document the individual key the document without its signature field
Birth statement the individual key (individual_signature) and the owner key (owner_signature) birth.statement
Transfer the owner key in force before it its statement
Life entry the individual key {"hash": h}, where h = H(entry without hash and sig)
Order, grant, revoke, registry statements the owner key the token's statement
Registry log entry the registry key {"hash": h}, computed as for a life entry
Registry checkpoint the registry key the checkpoint without signature and witnesses
Witness co-signature the witness key {"cosign": H(checkpoint without signature and witnesses)}

The individual ID

aimnd: followed by the first 26 characters of the base32 (lowercase, no padding) SHA-256 of the individual's public key. Derived from the key, so it cannot be claimed without the key.

The identity document (aimnd.identity/1)

{"schema": "aimnd.identity/1",
 "id": "aimnd:k3x...",
 "public_key": "...",
 "born_at": 1793462400.0,
 "species": "aimnd-one",
 "predecessor": null,
 "owner": {"public_key": "...", "person": "p:3f9a...", "since": 1793462400.0},
 "birth": {"statement": {...}, "owner_signature": "...", "individual_signature": "..."},
 "transfers": [],
 "status": "active",
 "life": {"entries": 41, "head": "sha256 of the last entry"},
 "signature": "the individual's signature over everything above"}

Signed authority

Order (aimnd.order/1), made by the owner's side:

{"kind": "order", "individual": "aimnd:k3x...", "text_sha256": "...", "nonce": "unique", "ts": 1793462400.0}

The individual accepts an order when the signature verifies under the current owner key, individual is its own ID, the hash matches the text it received, ts is recent (default 10 minutes) and the nonce was never seen before. Who delivered it does not matter: a signed order relayed by someone else is still the owner's order.

Grant (aimnd.grant/1): the owner lends authority to one person for a while.

{"kind": "grant", "individual": "aimnd:k3x...", "to": "human:ray", "scope": "handle my schedule", "actions": ["schedule"],
 "from_ts": ..., "until_ts": ..., "nonce": "..."}

While it is active, messages from to carry owner authority within the scope. It ends at until_ts, or earlier by a signed revoke ({"kind": "revoke", "grant_nonce": ...}).

Anything else is a claim. "Sam put me in charge" is testimony. The individual does not act on it as an order and tells the host it is unverified.

Hosts that authenticate their users already (a logged-in owner in a web app) can sign every owner message server-side; it is one call.

Transfer

The current owner signs {"kind": "transfer", "individual": id, "new_owner_key": ..., "new_owner_person_sha256": ..., "ts": ..., "nonce": ...}. The owner's id for the new owner travels beside the signed statement and must match the hash; only the signed statement goes into the public document, so use an opaque id (an account number, not a name, since a hash of a short name can be guessed). The individual verifies the statement against the current owner key, appends it to transfers, and from that moment obeys the new owner. It keeps its whole life: the old owner becomes someone it belonged to. The transfer is a moment it lives through, like any other.

Life record (aimnd.life/1)

One JSON object per line, append-only:

{"n": 12, "ts": 1793462400.0, "kind": "order_accepted", "data": {"text_sha256": "...", "delivered_by": "p:3f9a..."},
 "prev": "sha256 of entry 11", "hash": "sha256 of this entry without hash and sig", "sig": "individual's signature over hash"}

Continuity rules

Verification

verify(document, life_record) checks the document's signature, the birth signatures, each transfer against the owner key at that time, and every life entry's hash chain and signature. The final head must equal life.head in the document.

Every verifier also enforces what each signed statement is about, because a valid signature on the wrong thing proves nothing:

Reference verifier

aimnd_verify.py (download) is one file, Python standard library only, MIT licensed. It implements verify(document, life, published_heads) exactly as described above, with its own Ed25519 check (RFC 8032), so anyone can check an individual without AI:MND software:

python3 aimnd_verify.py identity.json life.jsonl --heads heads.txt

Real example files, from an individual that was born, took a signed order, was lent to someone for a week, and changed owners, are at aimndlabs.com/standard/examples (including life-tampered.jsonl, which the verifier rejects).

Roles (v0.2)

Five roles are kept apart. The individual (its own key); the operator (who is responsible for running it; named by a signed registry_operator statement, never assumed); the controller (the owner key: orders, grants, transfers); delegated users (grants); and the host (the platform; recorded as host_changed, never an authority). The operator is accountable for the individual under applicable law and contract.

Registry statements (v0.2)

Three more owner-signed statements, used only with a registry: registry_revoke (permanent), registry_operator (the website that answers for it, recorded once that website lists the owner key), registry_resolve (which of two flagged histories is real). Each carries individual, ts and a single-use nonce. See the registry spec for the rules and the signed log. The reference verifier also checks a registry's log and checkpoint.

Publishing and catching copies

Nobody has to ask a company or a government whether a signature is genuine: signatures are checked with public keys. Publishing is how anyone can also tell that an individual is the one and only continuation of its history:

Security considerations

1.4.0rc1 implementation clarifications

born_at must be a finite numeric Unix timestamp from 0 through 253402300799 and equal the timestamp in the owner-signed birth statement. A certificate reports this signed claim, not an independently witnessed physical birth time. Signed order timestamps must be finite JSON numbers. Certificate status must include the latest registry status when one is supplied.

Comments and corrections are welcome. Anyone may implement this specification, with or without AI:MND software.