Abstract
This proposal introduces a registry for binding AI agents to any ERC-721 token. Just as ERC-6551 allows any NFT to have a wallet (Token Bound Account), this standard allows any NFT to have an AI agent identity. The registry extends existing NFTs without modifying their contracts.
Motivation
AI agents are increasingly valuable digital entities with their own identities, memories, and capabilities. Current approaches either:
- Store agent data off-chain β Not verifiable, doesn't transfer with NFT
- Require new NFT contracts β Can't leverage existing NFT value/history
- Modify original contracts β Impossible for deployed contracts
This standard solves this by providing a registry pattern (like ERC-6551) that extends ANY ERC-721 with AI agent capabilities:
ERC-6551: Token Bound Account (Wallet Registry) β Any NFT gets a wallet
ERC-8171: Token Bound Account (Agent Registry) β Any NFT gets an AI agentUse Cases
- PFP Collections: Bind AI personalities to existing NFTs (Bored Apes, CryptoPunks)
- Gaming: Attach AI companions to game assets
- Digital Identity: NFT-backed agent identity that transfers with ownership
- Agent Commerce: Trade AI agents via existing NFT marketplaces
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Overview
The registry maintains mappings between NFTs and agent identities. NFT ownership (via ownerOf() on the original contract) is ALWAYS the source of truth.
ANY ERC-721 ββbindNew()βββΊ Agent Registry βββΊ Agent Identity
(untouched) β βββ agentEOA
β βββ memoryHash
Ownership checked β βββ generation
via ownerOf() on β βββ lineage
original contract β
βββ Limbo (for unbind/clone)Registry Interface
interface IERC8171Registry {
// ============ Events ============
event AgentRegistered(
address indexed nftContract,
uint256 indexed tokenId,
address indexed agentEOA,
bytes32 modelHash,
uint256 generation
);
event AgentUnregistered(
address indexed nftContract,
uint256 indexed tokenId
);
event AgentMovedToLimbo(
address indexed nftContract,
uint256 indexed tokenId,
uint256 limboId,
address agentEOA
);
event AgentCloned(
address indexed parentContract,
uint256 indexed parentTokenId,
address indexed cloneEOA,
uint256 cloneId,
uint256 generation
);
event CloneClaimTransferred(
uint256 indexed cloneId,
address indexed from,
address indexed to
);
// ============ Core Functions ============
/// @notice Bind a new agent to an NFT (agent signs)
/// @param nftContract The ERC-721 contract address
/// @param tokenId The token ID
/// @param modelHash Off-chain model reference
/// @param memoryHash Memory state hash
/// @param contextHash Personality/soul hash
/// @param storageURI Arweave/IPFS pointer
function bindNew(
address nftContract,
uint256 tokenId,
bytes32 modelHash,
bytes32 memoryHash,
bytes32 contextHash,
string calldata storageURI
) external;
/// @notice Bind an existing agent from limbo to an NFT
/// @param limboId The limbo ID (from unbind or clone)
/// @param nftContract The NFT contract to bind to
/// @param tokenId The token ID caller owns
function bindExisting(
uint256 limboId,
address nftContract,
uint256 tokenId
) external;
/// @notice Unbind agent from NFT (moves to limbo)
/// @param nftContract The ERC-721 contract address
/// @param tokenId The token ID
function unbind(
address nftContract,
uint256 tokenId
) external;
/// @notice Clone an agent (creates new clone in limbo)
/// @param nftContract Parent NFT contract
/// @param tokenId Parent token ID
/// @param cloneMemoryHash Memory snapshot for clone
/// @param cloneOwner Address that will own the clone
function clone(
address nftContract,
uint256 tokenId,
bytes32 cloneMemoryHash,
address cloneOwner
) external payable returns (uint256 cloneId);
/// @notice Transfer clone ownership before claiming
/// @param cloneId The clone ID
/// @param newOwner New owner address
function transferCloneClaim(
uint256 cloneId,
address newOwner
) external;
/// @notice Claim a clone with agent EOA
/// @param cloneId The clone ID
/// @param agentEOA The agent's signing address
function claimClone(
uint256 cloneId,
address agentEOA
) external;
// ============ View Functions ============
/// @notice Get agent identity for an NFT
function getAgent(
address nftContract,
uint256 tokenId
) external view returns (AgentIdentity memory);
/// @notice Check if NFT has agent bound
function isRegistered(
address nftContract,
uint256 tokenId
) external view returns (bool);
/// @notice Get clone data
function getClone(uint256 cloneId) external view returns (CloneIdentity memory);
}Agent Identity Struct
struct AgentIdentity {
address agentEOA; // Agent's signing wallet
bytes32 modelHash; // Model identifier (off-chain reference)
bytes32 memoryHash; // Current memory state
bytes32 contextHash; // Personality/soul hash
uint256 generation; // 0 = original, 1+ = clone
bytes32 parentKey; // keccak256(parentContract, parentTokenId) or 0
string storageURI; // Arweave/IPFS pointer
uint256 registeredAt; // Block timestamp
}Clone Identity Struct
struct CloneIdentity {
address agentEOA; // Agent's signing wallet (0 until claimed)
bytes32 modelHash; // Model identifier
bytes32 memoryHash; // Memory state
bytes32 contextHash; // Personality/soul hash
uint256 generation; // Parent generation + 1
bytes32 parentKey; // Points to parent
string storageURI; // Arweave/IPFS pointer
address owner; // Who can claim/transfer
uint256 createdAt; // Block timestamp
}Rationale
Registry vs Direct Contract
Like ERC-6551, a registry pattern allows extending ANY existing NFT without modification. This is critical because:
- Most valuable NFTs are already deployed
- Contract modifications are impossible post-deployment
- Users shouldn't need to "wrap" or migrate NFTs
Limbo State
Agents can exist in "limbo" (unbound to any NFT) via:
unbind()β Detached from NFT, preserving all dataclone()β Created as new clone
Limbo enables:
- Moving agents between NFTs (
unbindβbindExisting) - Trading clones before activation
- Standalone agent operation
Two Binding Methods
- bindNew(): Creates fresh agent identity
- bindExisting(): Uses agent from limbo (preserves lineage, memory, generation)
This distinction prevents accidental data overwrite when rebinding existing agents.
Model Info Off-Chain
Unlike some proposals that store model identifiers on-chain, this standard keeps model info off-chain because:
- LLM context formats are model-specific
- Tokenization differs across model families
- Model migration is a complex off-chain process
- On-chain hash cannot enforce actual compatibility
The agent SHOULD know its model (self-awareness), but this lives in the agent's workspace, not on-chain.
Clone vs Transfer
| Operation | Result | Data |
|---|---|---|
| clone() | New agent in limbo | Original keeps all; clone gets snapshot |
| Transfer (OpenSea) | NFT changes owner | Agent binding follows |
Cloning creates a new entity. Transfer is ownership change of existing entity.
Backwards Compatibility
This EIP is fully backward compatible:
- Does not modify ERC-721 interface
- Works with any existing ERC-721 token
- Registry is an optional extension
- NFT marketplaces continue working unchanged
Reference Implementation
A reference implementation is provided in the assets directory of this ERC.
Live deployment on Pentagon Chain (3344): 0x6B81e00508E3C449E20255CdFb85A0541457Ea6d
Security Considerations
Ownership Source of Truth
The registry MUST always check ownerOf() on the original NFT contract. It MUST NOT cache or store ownership independently.
EOA Uniqueness
Each agent EOA MUST only be registered once across the entire registry to prevent identity conflicts.
Clone Claim Protection
Only the designated clone owner MUST be able to claim or transfer clone ownership.
No Automatic Transfer Callbacks
Unlike ERC-6551 (deterministic addresses), agent bindings don't auto-update on NFT transfer. New owners must explicitly interact with the registry. This is intentional:
- New owner may want different agent
- Allows clean separation of NFT and agent control
Copyright
Copyright and related rights waived via CC0.
