---
eip: 8217
title: Agent NFT Identity Bindings
description: A per-chain singleton protocol that binds ERC-8004 agents to external NFT or token controllers.
author: Prem Makeig (@nxt3d)
discussions-to: https://ethereum-magicians.org/t/add-erc-8217-agent-nft-identity-bindings/28339
status: Draft
type: Standards Track
category: ERC
created: 2026-04-05
requires: 8004
---

## Abstract

This ERC defines a standard onchain metadata record and verification interface for expressing that an [ERC-8004](./eip-8004.md) agent identity is bound to an external NFT or tokenized asset contract. The metadata record stores only the binding contract address (20 bytes) under a reserved metadata key. The binding contract is expected to be deployed as a canonical per-chain singleton. Token standard, token contract, and token id are read from that contract via `bindingOf(agentId)` and are not duplicated in metadata.

## Motivation

[ERC-8004](./eip-8004.md) registrations are themselves NFTs. For an existing NFT to own an ERC-8004 registration, the two NFTs must be bound together. The owning NFT, called the master NFT, might be a project, character, or collection NFT. This ERC defines that binding. A canonical per-chain singleton binding contract records the link between an ERC-8004 agent id and its master NFT. The owner of the master NFT controls the bound ERC-8004 registration. When the master NFT is transferred, control follows automatically. The ERC-8004 record itself never changes.

Without a standard metadata format:

- clients cannot reliably discover that an agent is controlled through an external binding contract
- marketplaces and wallets cannot decode bound-token information consistently
- indexers must support adapter-specific formats

This ERC provides a canonical metadata key, a minimal binary encoding, a verification interface, and a per-chain singleton binding contract so clients can read the canonical bound-token record from `bindingOf(agentId)`.

## 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.

### Simplified Interface

Per-chain singleton binding contracts compliant with this ERC MUST expose a minimal interface that allows clients to:

- retrieve the stored binding for an agent id
- index newly written bindings

The required interface is:

```solidity
pragma solidity ^0.8.24;

interface IERCAgentBindings {
    enum TokenStandard {
        ERC721,
        ERC1155,
        ERC6909
    }

    struct Binding {
        TokenStandard standard;
        address tokenContract;
        uint256 tokenId;
    }

    event AgentBound(
        uint256 indexed agentId,
        TokenStandard indexed standard,
        address indexed tokenContract,
        uint256 tokenId,
        address registeredBy
    );

    function bindingOf(uint256 agentId) external view returns (Binding memory);
}
```

Contracts MAY expose richer functions such as registration, URI updates, metadata updates, wallet binding, or administrative upgrade controls, but these are outside the verification scope of this ERC.

### Deployment Model

The binding contract can be deployed on any L2 or on Mainnet as a per-chain singleton. Implementations MUST write the address of that chain's canonical binding singleton as the `agent-binding` metadata value. Multiple independently operated binding contracts on the same chain are NOT RECOMMENDED because they fragment trust assumptions and indexing.

### Metadata Key

Implementations compliant with this ERC MUST store the binding record under the [ERC-8004](./eip-8004.md) metadata key:

```text
agent-binding
```

### Binding Record Format

The metadata value for `agent-binding` MUST be exactly the 20-byte EVM address of the canonical binding contract:

```solidity
abi.encodePacked(bindingContract)
```

For example, the stored `bytes` are exactly the 20-byte address:

```text
0x9c4e8f2a1b7d6e3c0a5f8d2b9e1c4a7f3d6e8b0c
```

The field means:

- `bindingContract`: address of the canonical per-chain singleton that implements `IERCAgentBindings` and returns the canonical `Binding` for `bindingOf(agentId)`.

Token standard, token contract, and token id MUST be obtained only from `bindingOf` on this contract (see `IERCAgentBindings.Binding`).

The `AgentBound` event records the immutable binding when it is first written. `registeredBy` is the address that caused the binding to be registered.

### Required Behavior

An implementation that uses this ERC to represent a binding for an [ERC-8004](./eip-8004.md) agent:

1. MUST write the binding record under the `agent-binding` key as exactly 20 bytes (the binding contract address)
2. MUST ensure the address matches the contract that serves `bindingOf` for this agent
3. MUST treat `agent-binding` as a reserved key and prevent untrusted callers from overwriting it arbitrarily
4. MUST NOT update the binding for an `agentId` once it has been written
5. MUST emit `AgentBound(agentId, standard, tokenContract, tokenId, registeredBy)` when the binding is first written
6. MUST use the canonical per-chain binding singleton as the binding contract
7. MAY define control semantics in the binding contract, including [ERC-721](./eip-721.md) ownership or [ERC-1155](./eip-1155.md) / [ERC-6909](./eip-6909.md) balance-based control

This ERC standardizes discovery and canonical binding verification only. It does not standardize authorization rules inside the binding contract.

Bindings are immutable: once `agent-binding` has been written for an `agentId`, both the stored binding contract address and the `Binding` returned by `bindingOf(agentId)` MUST remain unchanged. This allows clients and indexers to verify a binding once and rely on the result without cache invalidation.

### Verification Flow

Clients verifying an [ERC-8004](./eip-8004.md) binding under this ERC MUST:

1. read the `agent-binding` metadata from the [ERC-8004](./eip-8004.md) registry
2. interpret the value as a single `address` (`bindingContract`); the length MUST be 20 bytes
3. call `bindingOf(agentId)` on `bindingContract` and use the returned `Binding` as the canonical token standard, token contract, and token id

If any step fails, clients MUST treat the binding relationship as unverified.

The `bindingContract` is expected to be the canonical per-chain singleton. `Binding.tokenContract` identifies the external token contract whose ownership or balance semantics are used by that singleton.

### Example Encoding

For `bindingContract = 0x9c4e8f2a1b7d6e3c0a5f8d2b9e1c4a7f3d6e8b0c`, the metadata payload is:

```text
0x9c4e8f2a1b7d6e3c0a5f8d2b9e1c4a7f3d6e8b0c
```

Clients then call `bindingOf(agentId)` on that address to obtain `standard`, `tokenContract`, and `tokenId`.

When the binding is first written, the binding contract emits:

```solidity
AgentBound(agentId, standard, tokenContract, tokenId, registeredBy)
```

## Rationale

### Why store the binding contract?

The token contract and token id alone are not sufficient. The same token may be interpreted differently by different authorization rules. Including the binding contract makes the control system explicitly discoverable and lets clients inspect or query the canonical per-chain singleton that actually defines the authorization rules.

### Why not store token standard, token contract, and token id in metadata?

Duplicating those fields in the registry would add unnecessary bytes to the metadata record. The binding contract is the single source of truth; metadata only points clients to which contract to query. Under the expected deployment model, that contract is the canonical per-chain singleton. Because bindings are immutable, clients and indexers can cache the result of `bindingOf(agentId)` after verification.

## Backwards Compatibility

This ERC is backwards compatible with:

- [ERC-8004](./eip-8004.md), because it only standardizes one metadata key and value format
- [ERC-721](./eip-721.md), [ERC-1155](./eip-1155.md), and [ERC-6909](./eip-6909.md) binding schemes, because it does not alter their token semantics

Existing [ERC-8004](./eip-8004.md) registries and adapters are not required to support this metadata key, but implementations that do can interoperate on a common discovery format.

## Test Cases

Metadata payload (always 20 bytes):

```text
bindingContract = 0x9c4e8f2a1b7d6e3c0a5f8d2b9e1c4a7f3d6e8b0c

=> 0x9c4e8f2a1b7d6e3c0a5f8d2b9e1c4a7f3d6e8b0c
```

For the same `bindingContract`, `bindingOf(agentId)` might return for example ERC-721 with `tokenId = 0`, ERC-1155 with `tokenId = 5`, or ERC-721 with `tokenId = 0x1234`; those values live only in the `Binding` struct from the binding contract, not in `agent-binding` metadata.

## Security Considerations

Clients MUST NOT assume that decoding `agent-binding` alone is sufficient to determine the current controller of an agent. The metadata reveals only which binding contract to use; the bound token and control semantics come from `bindingOf` and remain implementation-specific.

The trust for this system lies in the contract code of the binding contract. The result of the `bindingOf` function is only as secure and verifiable as the security of the binding contract itself. Clients SHOULD assess that contract (for example audits, reputation, and upgrade risk) before relying on its return values.

We expect the binding contract to be deployed as a singleton per chain. A single canonical binding contract per chain concentrates security and trust around one well-audited contract, and lets indexers and clients watch and verify a single contract per chain instead of an open-ended set of binding contracts.

Implementations MUST store the address of the canonical per-chain singleton under `agent-binding`. Deployments that use multiple binding contracts on the same chain create fragmented trust assumptions and require clients and indexers to discover, assess, and monitor each contract independently.

Clients MUST:

1. decode the binding metadata (20-byte `bindingContract` address)
2. inspect or query the referenced `bindingContract`
3. read the canonical binding with `bindingOf(agentId)`

Implementations MUST reserve the `agent-binding` metadata key so that untrusted callers cannot overwrite or forge the canonical record after registration.

Implementations MUST NOT change the binding contract address stored under `agent-binding` or the `Binding` returned by `bindingOf(agentId)` after the binding has been written. Upgradeable implementations MUST preserve this immutability across upgrades.

This metadata format is EVM-address based. It does not describe non-EVM bindings and does not itself encode chain context.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
