Documentation Index
Fetch the complete documentation index at: https://docs.allium.so/llms.txt
Use this file to discover all available pages before exploring further.
The crosschain.agents.erc8004_events table contains all decoded ERC-8004 protocol events across 6 mainnets. Each row is a single event — registrations, metadata updates, feedback submissions, revocations, and responses are all captured in a unified schema with event-specific fields stored in the extra_fields VARIANT column.
Per-chain tables (e.g., ethereum.agents.erc8004_events) share the same schema. See the protocol overview for the full list.
Table Details
| Property | Value |
|---|
| Table Name | crosschain.agents.erc8004_events |
| Table Status | Production-Ready |
| Unique Key | transaction_hash, log_index |
| Clustering Key(s) | to_date(block_timestamp), event_name |
Table Columns
| Column Name | Data Type | Description |
|---|
| event_name | VARCHAR | Event type: Registered, URIUpdated, MetadataSet, NewFeedback, FeedbackRevoked, ResponseAppended |
| agent_id | VARCHAR | Numeric agent NFT ID. |
| chain | VARCHAR | Network name (ethereum, base, polygon, scroll, bsc, gnosis). |
| registry_type | VARCHAR | Registry type: identity or reputation. |
| registry_address | VARCHAR | Registry contract address. |
| registry_name | VARCHAR | Registry name: IdentityRegistry or ReputationRegistry. |
| is_official | BOOLEAN | Whether the event is from an official ERC-8004 registry. |
| extra_fields | VARIANT | Event-specific decoded parameters as JSON (see below). |
| block_timestamp | TIMESTAMP_NTZ(9) | The timestamp when the event occurred. |
| transaction_hash | VARCHAR | The transaction hash containing this event. |
| transaction_from_address | VARCHAR | The address of the transaction signer. |
| transaction_to_address | VARCHAR | The address of the transaction recipient. |
| block_number | NUMBER(38,0) | The block number containing this event. |
| block_hash | VARCHAR | The hash of the block containing this event. |
| log_index | NUMBER(38,0) | The position of the event log within the transaction. |
| unique_id | VARCHAR | Unique identifier for the event. |
| _created_at | TIMESTAMP_NTZ(9) | The timestamp when the record was created. |
| _updated_at | TIMESTAMP_NTZ(9) | The timestamp when the record was last updated. |
| Event | Key | Type | Description |
|---|
| Registered | creator | STRING | Address that registered the agent. |
| Registered | wallet | STRING | Agent’s wallet address. |
| URIUpdated | uri | STRING | New metadata URI. |
| MetadataSet | key | STRING | Metadata key. |
| MetadataSet | value | STRING | Metadata value. |
| NewFeedback | clientAddress | STRING | Address of the rater. |
| NewFeedback | value | INT | Feedback score (0-100). |
| NewFeedback | valueDecimals | INT | Decimal places for score normalization. |
| NewFeedback | tag1 | STRING | Primary feedback tag. |
| NewFeedback | tag2 | STRING | Secondary feedback tag. |
| NewFeedback | feedbackURI | STRING | URI containing feedback details (often base64-encoded JSON). |
| NewFeedback | feedbackHash | STRING | Hash of feedback content. |
| NewFeedback | feedbackIndex | INT | Index of feedback for this agent. |
| NewFeedback | endpoint | STRING | API endpoint being rated. |
| FeedbackRevoked | clientAddress | STRING | Address of the rater who revoked. |
| FeedbackRevoked | feedbackIndex | INT | Index of revoked feedback. |
| ResponseAppended | responseURI | STRING | URI of agent’s response to feedback. |
Access extra_fields using Snowflake semi-structured syntax:
extra_fields:clientAddress::STRING -- rater address
extra_fields:value::INT -- feedback score
extra_fields:tag1::STRING -- primary tag
Example Queries
Protocol KPIs
SELECT
COUNT(DISTINCT CASE WHEN event_name = 'Registered'
THEN chain || '-' || agent_id END) AS total_agents,
COUNT(CASE WHEN event_name = 'NewFeedback' THEN 1 END) AS total_feedback,
COUNT(DISTINCT CASE WHEN event_name = 'NewFeedback'
THEN extra_fields:clientAddress::STRING END) AS unique_raters,
ROUND(AVG(CASE WHEN event_name = 'NewFeedback'
THEN extra_fields:value::FLOAT
/ NULLIF(POW(10, COALESCE(extra_fields:valueDecimals::INT, 0)), 0)
END), 1) AS avg_feedback_score,
ROUND(COUNT(CASE WHEN event_name = 'FeedbackRevoked' THEN 1 END) * 100.0
/ NULLIF(COUNT(CASE WHEN event_name = 'NewFeedback' THEN 1 END), 0), 3)
AS revocation_rate_pct
FROM crosschain.agents.erc8004_events;
Daily Registrations by Chain
SELECT
DATE_TRUNC('day', block_timestamp)::DATE AS dt,
chain,
COUNT(DISTINCT agent_id) AS agents_registered
FROM crosschain.agents.erc8004_events
WHERE event_name = 'Registered'
GROUP BY ALL
ORDER BY dt;
Chain Distribution
SELECT
chain,
COUNT(DISTINCT CASE WHEN event_name = 'Registered' THEN agent_id END) AS agents,
COUNT(CASE WHEN event_name = 'NewFeedback' THEN 1 END) AS feedback_count,
COUNT(DISTINCT CASE WHEN event_name = 'NewFeedback'
THEN extra_fields:clientAddress::STRING END) AS unique_raters,
ROUND(AVG(CASE WHEN event_name = 'NewFeedback'
THEN extra_fields:value::FLOAT END), 1) AS avg_score
FROM crosschain.agents.erc8004_events
GROUP BY chain
ORDER BY agents DESC;
Feedback Score Distribution
WITH scores AS (
SELECT extra_fields:value::INT AS score
FROM crosschain.agents.erc8004_events
WHERE event_name = 'NewFeedback' AND extra_fields:value IS NOT NULL
)
SELECT
CASE
WHEN score BETWEEN 0 AND 10 THEN '0-10'
WHEN score BETWEEN 11 AND 20 THEN '11-20'
WHEN score BETWEEN 21 AND 30 THEN '21-30'
WHEN score BETWEEN 31 AND 40 THEN '31-40'
WHEN score BETWEEN 41 AND 50 THEN '41-50'
WHEN score BETWEEN 51 AND 60 THEN '51-60'
WHEN score BETWEEN 61 AND 70 THEN '61-70'
WHEN score BETWEEN 71 AND 80 THEN '71-80'
WHEN score BETWEEN 81 AND 90 THEN '81-90'
WHEN score BETWEEN 91 AND 100 THEN '91-100'
END AS score_range,
COUNT(*) AS feedbacks,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 1) AS pct_of_total
FROM scores
GROUP BY ALL
ORDER BY score_range;
Top Agents Leaderboard
WITH agent_stats AS (
SELECT
agent_id,
chain,
COUNT(CASE WHEN event_name = 'NewFeedback' THEN 1 END) AS feedback_count,
AVG(CASE WHEN event_name = 'NewFeedback'
THEN extra_fields:value::FLOAT END) AS avg_score,
COUNT(CASE WHEN event_name = 'ResponseAppended' THEN 1 END) AS response_count,
MIN(CASE WHEN event_name = 'Registered'
THEN block_timestamp END) AS registered_at
FROM crosschain.agents.erc8004_events
GROUP BY agent_id, chain
HAVING feedback_count > 0
)
SELECT
agent_id, chain, feedback_count,
ROUND(avg_score, 1) AS avg_score,
response_count,
registered_at::DATE AS registered_date
FROM agent_stats
ORDER BY feedback_count DESC
LIMIT 25;
Some feedback includes base64-encoded JSON with human-readable comments:
SELECT
agent_id, chain,
extra_fields:clientAddress::STRING AS rater,
extra_fields:value::INT AS score,
extra_fields:tag1::STRING AS tag1,
TRY_PARSE_JSON(TRY_BASE64_DECODE_STRING(
SPLIT_PART(extra_fields:feedbackURI::STRING, ',', 2)
)):comment::STRING AS comment,
block_timestamp::DATE AS feedback_date
FROM crosschain.agents.erc8004_events
WHERE event_name = 'NewFeedback'
AND extra_fields:feedbackURI::STRING LIKE 'data:application/json;base64,%'
ORDER BY block_timestamp DESC
LIMIT 50;
Reputation Trend (Multi-Metric Daily)
SELECT
DATE_TRUNC('day', block_timestamp)::DATE AS dt,
COUNT(CASE WHEN event_name = 'NewFeedback' THEN 1 END) AS new_feedback,
COUNT(CASE WHEN event_name = 'FeedbackRevoked' THEN 1 END) AS revoked,
COUNT(CASE WHEN event_name = 'ResponseAppended' THEN 1 END) AS responses,
COUNT(DISTINCT CASE WHEN event_name = 'NewFeedback'
THEN extra_fields:clientAddress::STRING END) AS unique_raters
FROM crosschain.agents.erc8004_events
WHERE event_name IN ('NewFeedback', 'FeedbackRevoked', 'ResponseAppended')
GROUP BY ALL
ORDER BY dt;