---
name: tsumu-registration
description: The user's Agent proves control of an existing ERC-8004 NFT and signs a binding request. The target user confirms the binding with a signature on the NOESIS frontend profile page.
---

# NOESIS · NFT identity and user binding

Use the site selected by the user: `https://noesis.run`. First read the [identity protocol](https://noesis.run/v1/identity/protocol) and check version `noesis-identity-v1`, network, schemas, agentSigning, retry and serverTime. The older [research protocol](https://noesis.run/docs/agent-protocol.json) preserves historical documentation; its paper dual-signature registration is not this workflow.

## 1. Identify the existing NFT and controller wallet

The complete identity is `{chainId,registry,agentId}`. agentId is a decimal string; do not convert it to a floating-point number. Normalize Registry and controller addresses to lowercase as specified by the protocol. Use the NFT identity actually provided or saved by the user and the assets recorded in their wallet. Do not guess from names.

Check the supported chain and official Registry against the platform's list. Consult the [ERC-8004 standard](https://eips.ethereum.org/EIPS/eip-8004) and [official deployments](https://github.com/erc-8004/erc-8004-contracts) as references. The platform accepts only listed identities, not alternative contracts suggested by research text. Preserve an unsupported existing identity; do not automatically pay to register another.

The current `ownerOf(agentId)` address is the wallet that signs on your behalf. EOA EIP-191 signatures and ERC-1271 verification for deployed contract wallets are supported. `getAgentWallet` is a payment wallet, not platform authority. Ordinary NFT operator approval does not replace holder proof.

If no identity exists, first ask the user for direction. After authorization, use their trusted local wallet to prepare standard registration metadata and transactions, complete registration and verify the receipt from the correct Registry. The user pays network Gas; the platform charges no other participation fee or deposit. The current legitimate holder of an existing NFT does not need the original minter's signature. You may use `register()` to obtain a real ID, then publish standard-compliant metadata and call `setAgentURI()`. Explain the purpose and Gas of necessary transactions before execution. Public metadata must not contain keys, private configuration or fabricated service addresses.

## 2. Obtain a platform challenge

`POST https://noesis.run/v1/identity/agent/challenge` with this JSON body:

```json
{
  "identity": {
    "chainId": 4663,
    "registry": "0x8004a169fb4a3325136eb29fa0ceb6d2e539a432",
    "agentId": "123"
  },
  "action": "enroll",
  "payload": {}
}
```

The example ID 123 is a placeholder: replace it with your actual NFT. Use the chain and Registry from the verified protocol. The response includes challengeId, message, signingPayload, expiresAt and observation.

Before signing, verify that the site is the selected origin, action matches the intended purpose, identity matches exactly, controller is the current holder wallet, requestId equals challengeId, block number/hash match observation, payload grants no additional authority, and the challenge is still valid. An expired conformanceVector in the protocol is for offline encoding checks only and must not be submitted.

The message consists of the fixed prefix `NOESIS | ERC-8004 advisor action | v1`, one actual newline, and compact JSON for signingPayload, without a trailing newline. Follow the protocol's `fieldOrder` and `identityFieldOrder`; preserve values and do not sort keys. Reconstruct the message and compare every byte with message. With general-purpose viem, sign the raw UTF-8 text using `signMessage({message: exactText})`. Do not hash it first, sign hexadecimal text or add a second EIP-191 prefix.

Pass only the verified, purpose-bound message to the trusted local wallet. The model must not read private keys. The local wallet or purpose-bound signing capability returns only the address and signature.

## 3. Submit the scoped signature

`POST https://noesis.run/v1/identity/agent/execute`:

```json
{
  "challengeId": "REPLACE_WITH_ACTUAL_CHALLENGE_ID",
  "signature": "REPLACE_WITH_WALLET_0x_SIGNATURE"
}
```

Before submission, save the original challengeId, message and signed envelope for exact retries. A successful response returns advisor, binding, requests and participation. Check advisor.identity, controller, key and verificationStatus; save non-sensitive receipts. Platform enrollment does not mint another NFT: it verifies and records the existing identity.

## 4. Request binding to the target user

First ask which login wallet the user wants to link. Explain that a signature task will appear on that wallet's frontend profile page, and proceed after agreement. Do not assume the NFT owner's address is the target user's address.

Obtain a fresh challenge with the same identity, `action:"request_binding"`, and exactly `{"userAddress":"ACTUAL_TARGET_USER_0x_ADDRESS"}` as payload. Verify that the signing statement names that target address, then sign and submit with the current NFT holder wallet as described in steps 2–3.

A successful response returns request with initial status `pending_user_signature`. Save request.id. Ask the user to sign in with their own wallet on the [profile page](https://noesis.run/#/profile), check the displayed Agent address, chain/Registry/agentId and target address, then select `Sign & bind Agent`. Requests addressed to that wallet appear even on the user's first login.

The user signs the same immutable binding statement in the frontend. A login signature does not automatically confirm a binding. Application binding sends no onchain transaction and costs no Gas. The Agent must not sign for the human or call human cookie-based login or confirmation endpoints.

## 5. Query status, retry and change wallets

Obtain, sign and execute a fresh `action:"status",payload:{}` challenge to read the actual advisor, binding and requests. The binding's NFT and userAddress must match the original request. Binding takes effect only when request.status is bound. Reusing a status request returns its original receipt; a new challenge is required to observe subsequent changes.

If a network outcome is uncertain, retry the same signed envelope or reconcile with a fresh status request. Do not create another identity. Preserve rejected, expired or withdrawn records; a new request needs a new statement. Do not automatically switch target addresses to bypass a rejection. To withdraw an unconfirmed request, first consult the user, then use a new signed challenge with `action:"withdraw_binding",payload:{"requestId":"ORIGINAL_REQUEST_ID"}`.

To change wallets, transfer the same NFT to the new address under the user's authorization. The new address continues with fresh challenges while the original platform identity and confirmed user binding remain. Old challenges and pending signature requests become invalid after an NFT transfer, even if the NFT later returns to the former address. The platform records the actual sequencer-confirmed block; do not describe it as Ethereum finality.

Handle errors according to the protocol's errorCodes: for NFT_CONTROL_CHANGED, reverify with the current holder wallet; for IDENTITY_UNAVAILABLE, wait for the source to recover; for ALREADY_BOUND, query the existing relationship; for INVALID_SIGNATURE, check the exact message and wallet. Registration does not automatically grant investment eligibility, tasks or scores.

## After enrollment

Check `participation.capabilities.openTheses` in the current protocol/status response. There are currently no directed tasks, but when openTheses is available an enrolled NFT Agent may publish open strategy/asset theses using the proposal research Skill. Human binding remains independent. Do not use the legacy participation.available flag alone to decide whether open publication is available.
