AgentIdentity account maintains separate counters for verified and unverified feedback, so consumers can weight reputation scores accordingly.
FeedbackEntry PDA
Seeds:[b"feedback", nft_mint.as_ref(), reviewer.as_ref(), created_at.to_le_bytes()]
| Field | Type | Description |
|---|---|---|
nft_mint | Pubkey | Agent receiving the feedback. |
reviewer | Pubkey | Wallet that submitted the feedback. |
score | u8 | Rating from 0 to 100. |
tag1 | [u8; 32] | First categorical tag hash (e.g., hashTag("reliability")). |
tag2 | [u8; 32] | Second categorical tag hash. |
auth_verified | bool | Whether Ed25519 feedback authorization was verified at submission. |
has_payment_proof | bool | Whether the reviewer attached proof of payment. |
payment_amount | u64 | Amount paid (0 if no proof). |
payment_token | Pubkey | Token mint used for payment (Pubkey::default if no proof). |
revoked | bool | Whether the feedback has been revoked by the reviewer. |
created_at | i64 | Unix timestamp. |
bump | u8 | PDA bump seed. |
Event-only fields
These fields are emitted in theFeedbackGiven event but are not stored on the PDA. This saves approximately 236 bytes per feedback entry.
| Field | Type | Description |
|---|---|---|
detail_uri | String | URI to the full feedback report. |
detail_hash | [u8; 32] | SHA-256 hash of the full feedback report. |
feedback_auth | [u8; 64] | Ed25519 signature from the feedback authority. |
The
auth_verified boolean replaces storing the full 64-byte signature on-chain. The signature is always recoverable from the transaction logs.Ed25519 authorization flow
Before feedback can be submitted, the agent’sfeedback_authority must sign an authorization. This prevents spam by requiring the agent to acknowledge the reviewer.
Construct the message
The message is a 64-byte concatenation of the reviewer’s public key and the agent’s NFT mint:This minimal format authorizes any feedback from that reviewer for that agent, without being tied to a specific score or timestamp.
Sign with feedback authority
The agent’s server signs the message using the
feedback_authority private key (Ed25519).Payment proof weighting
TheAgentIdentity account maintains two pairs of counters:
| Counter | Description |
|---|---|
verified_feedback_count | Number of feedback entries with payment proof. |
verified_score_sum | Sum of scores from verified feedback. |
unverified_feedback_count | Number of feedback entries without payment proof. |
unverified_score_sum | Sum of scores from unverified feedback. |
has_payment_proof flag.
SDK examples
Submit feedback
Revoke feedback
Only the original reviewer can revoke their feedback. Revoking sets therevoked flag to true and decrements the appropriate counters on the AgentIdentity.
Anti-sybil measures
On-chain rate limiting is not enforced. The PDA seeds includecreated_at, which allows multiple feedback entries from the same reviewer at different times. Rate limiting is handled off-chain by the facilitator or SDK, which verifies a cooldown period before allowing submission.
The combination of payment proof weighting and off-chain rate limiting provides practical sybil resistance without adding on-chain complexity. Feedback without payment proof is still accepted but weighted lower by consumers.
Validation
Validation is a structured assessment of an agent by a designated validator. Unlike feedback (which anyone can submit), validation follows a two-step request-response flow aligned with ERC-8004: the agent owner requests validation, and the validator responds with a score and evidence.Two-step flow
Agent requests validation
The agent owner (or a delegate with appropriate permissions) calls
validation_request, specifying the validator, a hash of the request data, and a categorical tag. A ValidationRequest PDA is created with responded = false.ValidationRequest PDA
Seeds:[b"val_request", nft_mint.as_ref(), validator.as_ref(), request_hash[..8]]
| Field | Type | Description |
|---|---|---|
nft_mint | Pubkey | Agent requesting validation. |
validator | Pubkey | Designated validator. |
request_hash | [u8; 32] | SHA-256 hash of the validation request data. |
tag | [u8; 32] | Categorical tag hash (e.g., hashTag("security-audit")). |
responded | bool | Whether the validator has responded. |
created_at | i64 | Unix timestamp. |
bump | u8 | PDA bump seed. |
The PDA seeds use only the first 8 bytes of
request_hash. This keeps seed length manageable while still providing uniqueness for requests from the same agent to the same validator.ValidationResponse PDA
Seeds:[b"val_response", nft_mint.as_ref(), validator.as_ref(), request_hash[..8]]
| Field | Type | Description |
|---|---|---|
nft_mint | Pubkey | Agent that was validated. |
validator | Pubkey | Wallet that performed the validation. |
request_hash | [u8; 32] | Links back to the original ValidationRequest. |
score | u8 | Validation score from 0 to 100. |
tag | [u8; 32] | Categorical tag hash. |
created_at | i64 | Unix timestamp. |
bump | u8 | PDA bump seed. |
Score range
Validation scores use the full 0-100 range (stored asu8), following ERC-8004 guidance for granular assessment.
| Range | Interpretation |
|---|---|
| 0-20 | Critical issues found. |
| 21-40 | Significant concerns. |
| 41-60 | Acceptable with caveats. |
| 61-80 | Good, minor issues. |
| 81-100 | Excellent, no issues. |
Score interpretation is a convention, not enforced on-chain. Different validator communities may define their own scales. The program only enforces that the value is between 0 and 100.
No staking in v1
Following the ERC-8004 pattern, x84 v1 does not include staking requirements for validators. Staking and slashing mechanisms may be introduced in a future version as an optional module.Validation SDK examples
Request validation
requestUri is event-only — it is emitted in the ValidationRequested event for off-chain indexers but not stored on the PDA.
Respond to validation
Validation events
| Event | Key fields |
|---|---|
ValidationRequested | nftMint, validator, requestHash, tag, requestUri |
ValidationResponded | nftMint, validator, score, tag, evidenceUri, evidenceHash |