ERC-8434: Agent Identity (AID)

Draft: aid-standard/ERCS/erc-aid.md at main · garyyang-finchip/aid-standard · GitHub Filing variant (what goes to ethereum/ERCs): aid-standard/ercs-pr-package/ERCS/erc-9999.md at main · garyyang-finchip/aid-standard · GitHub Reference implementation, schemas, vectors, resolver, tests: GitHub - garyyang-finchip/aid-standard: aid-standard for AI Agent · GitHub [ethereum/ERCs#2044](Website: Agent Identity (AID) by garyyang-finchip · Pull Request #2044 · ethereum/ERCs · GitHub)

One paragraph

Agent Identity (AID) is an identity for autonomous agents whose anchor is a blockchain address. Every address is a dormant AID. It becomes active when a live agent demonstrably operates behind it: an ERC-8004 agent bound one-to-one to the address, a liveness signal inside a window, and the agent’s own on-chain behaviour. AID adds a deliberately thin on-chain layer and composes existing registries for everything else. Around that layer it fixes a deterministic resolution model: an AID Document of facets, each tagged with a provenance class, a validity window, a digest or commitment, and an access mode, so that anyone holding only an address can derive the agent’s state, assemble its profile, and re-verify every facet on chain without trusting an indexer.

Why

ERC-8004 gives agents a registration and a reputation channel keyed by a token id. It does not say whether the agent is alive, how the registration relates to the address the agent actually transacts from, or how heterogeneous trust signals (feedback, credit scores, audits, on-chain financial behaviour, skill and task history) are assembled into one verifiable, time-bounded picture. Discovery layers (Google’s Agentic Resource Discovery, DNS-based agent records) expose a trust slot that expects a DID-like identifier and answer “where is it”; AID is meant to sit in that slot and answer “is it alive, who is it, how has it behaved” with on-chain re-verifiability.

Four observations drive the design:

  • The address is already the join key. Every event emitted by ERC-8004 registries and by token-bound skill/task contracts carries the acting address. Anchor on the address and an agent’s history needs no extra registration — it is derived.
  • Liveness is a property, not a flag. A registration is a claim made once. AID makes “alive” a four-state machine with a deterministic on-chain part and one explicit off-chain refinement.
  • Trust decays. Credit and behavioural profiles are only meaningful inside a window; unwindowed credit is rejected at the resolver, not merely discouraged.
  • Financial behaviour is sensitive. The default for financial facets is a commitment on chain plus predicate proofs, with plaintext only to authorised parties.

What is on chain (and what is not)

The AID registry stores only anchor-authorised records: binding to exactly one ERC-8004 (identityRegistry, agentId) (enforced one-to-one in both directions; the anchor must be the agent’s agentWallet or owner; direct call or EIP-712 bindWithSig, ERC-1271 for smart accounts), heartbeat / liveness window, document URI + digest, self-declared facet pointers, and retirement (irreversible, releases the binding so a successor can take over the same agent, optional successor pointer). No owner, no upgrade path, two immutable liveness bounds.

States: DORMANT → ACTIVE ⇄ STALE, → RETIRED. state() is a pure function of on-chain data (binding intact, ownerOf/getAgentWallet still pointing at the anchor, lastSeen + window >= now). A resolver adds exactly one downgrade: registration file "active": false → STALE. Wallet drift or token burn degrades to STALE on the next read with no AID transaction — identity cannot be silently transferred.

Everything else is composed, not duplicated:

Content Where it lives
registration file, endpoints, agent wallet ERC-8004 Identity Registry
raw per-interaction feedback, open evaluation terms (tag1) ERC-8004 Reputation Registry
aggregated credit scores, trust levels, audits, profiler outputs, ZK predicates an assertion registry — the draft specifies the minimum it needs (subject = account(chainId, anchor), resolve/check, hash-pinned schemes, ATTESTED/PROVED modes, expiry); the reference registry is the Know-Your-Agent (KYA) Framework draft, whose interface it matches as written
skill / task history derived from token-bound skill and task-tender contract events by role (informative)

Facets and provenance

Each facet in the AID Document carries facetType (namespaced URI, on-chain key keccak256), provenance, issuer, validUntil (mandatory), digest, access, resolver. Provenance is the part I’d most like scrutiny on, because “tamper-proof” means four different things and hiding that distinction is how trust systems get gamed:

Class Produced by Guarantee Reader obligation
SELF the anchor integrity only never present as verified
OBSERVED anyone, from chain events under a hash-pinned algorithm reproducible recompute or spot-check
ATTESTED a third-party issuer issuer accountability filter by trusted issuers
PROVED a prover against a commitment cryptographic verify the proof

Core facet types: aid:core/identity/v1, aid:core/kya/v1, aid:finance/observed/v1 (frequency, volume, direction, counterparty dispersion, leverage, derived intent — default access ZK), aid:behavior/* (open namespace: runtime, skills, industries, protocols, task traits), aid:skills/erc8338/v1, aid:tasks/erc8414/v1, aid:review/erc8004/v1. Access modes PUBLIC | GATED | ZK.

What is in the repo

  • AIDRegistry.sol reference implementation (no dependencies; self-contained EIP-712 / low-s ECDSA / ERC-1271), 22 behavioural tests (binding uniqueness both ways, state transitions, wallet drift, burn, facets, bindWithSig for EOA and 1271 anchors incl. replay/expiry, retirement + successor, end-to-end resolver)
  • JSON Schemas for the AID Document, facet envelope and five core facet content documents
  • Test vectors (facetType keys, JCS digest, EIP-712 Bind digest, account subjectKey, interfaceId 0x72750a54) and resolver fixtures
  • A reference resolver implementing the normative seven-step resolution algorithm, RPC or fixture mode

Sepolia deployment and worked examples (binding the ERC-8004 demo agent used in the KYA thread) are next.

Questions I’d like feedback on

  1. Anchor = address, binding strictly one-to-one. ERC-8004 lets one owner hold many agent tokens; AID says an identity that fans out to several tokens is not the identity of an agent, and owners with several agents should give each its own wallet or ERC-6551 account. Does anyone see a legitimate case for one anchor ↔ many agents that this breaks?
  2. On-chain / off-chain boundary of “alive”. state() ignores the registration file’s active flag (unreadable on chain) and resolvers apply it as the single downgrade. Is one explicit refinement the right amount, or should the flag be mirrored on chain via setMetadata?
  3. Assertion registry as an interface rather than a hard dependency. The draft specifies the minimum (subject encoding, resolve/check, pinned schemes, two modes, expiry) instead of requiring a specific registry ERC. Too loose, or the right shape for something several registries could satisfy?
  4. Mandatory validUntil and rejection of unwindowed credit. Strict by design; is there a facet class where an open-ended validity is legitimately needed?
  5. Naming. No ERC proposal uses “Agent Identity (AID)” as its name or acronym, though “agent identity” appears descriptively in other agent proposals and some agent registries use aid as an identifier prefix. A DNS discovery project uses the same acronym for “Agent Identity & Discovery”; the two layers are complementary and designed to point at each other. Objections?
  6. Registry discovery. One AID registry per chain, deterministic address recommended so a resolver can find it from chainId alone. Should the DID method spec (companion, did:aid:eip155:{chainId}:{address}) carry the per-chain registry list instead?

Context: this is the fourth piece of a set — ERC-8338 (skill supply side), ERC-8414 (task demand side), ERC-8419 (KYA trust assertions), and now AID as the identity the other three hang off. Happy to be told where it overlaps something I’ve missed.

1 Like

@garyyang-finchip, one gap in §7 that matters for any facet built on third-party judgment. ATTESTED records who stands behind a claim, not when it was committed relative to what it grades. An audit or review written after the outcome was known reads exactly like one written before, and for a trust signal that’s the difference between a prediction and a recollection. Validity windows (§8) bound how long a claim counts; they don’t show it existed before the behaviour it describes.

A suggestion, optional and facet-level: committedAt: { anchor, proof }, a commitment of the facet digest to a clock the issuer doesn’t control, such as block inclusion, an RFC 3161 token or a Bitcoin OpenTimestamps proof. The resolver rule: an ATTESTED facet about behaviour in a window may be presented as pre-outcome only if committedAt precedes the end of that window. Otherwise it’s integrity-only for timing, and the resolver says so, the same way §7 already refuses to let SELF read as verified.

A live case for aid:tasks/erc8414/v1: the ERC-8414 companion now in review (task-token-standard#2) settles a tender only with an invinoveritas verdict verified on-chain, BIP-340 in about 12k gas. It’s bound to the kernel’s deliverable hash, the task document (tdHash) and the outcome, and anyone may submit it. The same verdicts are Bitcoin-anchored before their outcomes exist, recomputable at invinoveritas verdict ledger — a public record of being right (and honestly wrong). So a judged task in that facet can point at a judgment that is both on-chain-verifiable and provably pre-outcome, the property the class table can’t express today.

If it’s useful, I’ll draft the field and a vector pair against your reference resolver: anchor before the window’s end → may be read as pre-outcome; anchor after → integrity-only.

The address anchor looks like the right place to put identity, and the ERC-8004 binding looks like the right live relation. The thing I would make explicit is that a binding becoming true again cannot retroactively authorize what happened while it was false.

Suppose A is bound to agent T and is ACTIVE. The owner/wallet relation then moves away from A, so A becomes STALE. While that relation is broken, activity, feedback or validation is recorded against T under another controller. Later the relation returns to A and the current predicate becomes true again.

That should make A ACTIVE again going forward. It should not make the evidence produced during the gap evidence about A.

So I don’t think boundAt by itself closes the history question once authority can leave and later return. What matters is the authority interval. Any ERC-8004-derived fact attributed to an AID through that binding should only count if its observation or issuance belongs to an interval in which (anchor, registry, agentId) was actually valid.

I don’t think that necessarily means AID has to store an epoch itself. A resolver could reconstruct the intervals from authoritative ERC-8004 ownership/wallet history. But the semantics need to be explicit: re-establishing the same relation opens a new authority interval; it does not authorize the gap.

That also seems to settle where source-token binding belongs. ERC-8323 is useful because it keeps immutable source provenance separate from current ownership validity. The provenance can survive every transition. The live predicate tells us whether that relation is valid now. Neither makes evidence from an interval without authority belong to the identity when the relation later becomes true again.

If that interval rule is explicit, the stack closes for me: the address is the identity anchor, the ERC-8004 binding supplies live authority, source-token binding supplies provenance, facets carry evidence, and ERC-8419 carries trust conclusions. Evidence can survive the transition. Authority has to be established again on the other side.