Giving an AI agent on-chain data? Do not start with raw RPC

July 4, 20266 min readBy Harman Kamboj
AIAgentsWeb3Indexers

A while back I watched an agent try to answer a plain question about one wallet's trading history by reading the chain itself. It fired off a pile of RPC calls, pulled thousands of raw logs, burned a fortune in tokens trying to decode them by hand, and still got the answer partly wrong, because two of the blocks it had trusted got reorged out from under it a minute later. That was the run that settled my opinion on how to give an AI agent on-chain data. Not through raw RPC. Put an indexer in between and let the agent ask a real question instead of doing data engineering it is bad at.

I say this as someone who has spent a lot of years on both ends of this. I have built the indexers, for a top-10 crypto's web platform and for a DeFi exchange, and lately I have been building the agents that want to read what those indexers produce. The mistake I keep seeing is people wiring a shiny new agent straight to an RPC endpoint because that is the first thing the docs show you. It works in a demo. It falls apart the moment the question gets real.

Raw chain data is not a data source, it is a receipt pile

Here is the thing nobody tells you when you are new to this. The blockchain does not store your app's data. It stores a ledger of what happened, in a shape optimized for consensus, not for questions. A swap is not a row that says who traded what. It is a log entry with a topic hash and a blob of hex you have to decode against an ABI you had better have on hand. To reconstruct one wallet's history you walk a range of blocks, pull the logs, decode each one, join them to token metadata, and sort them into an order the chain never actually promised you. That is a real engineering job. Handing it to a language model token by token is the most expensive and least reliable way to do it I can think of.

And the model is genuinely bad at the parts that matter here. It will happily hallucinate a decoded value, mix up token decimals, or invent an ordering that looks plausible and is wrong. None of that is the model being dumb. It is the model being asked to be a deterministic parser, which is not what it is for.

The recent stuff is a moving target

Even if the agent decodes everything perfectly, the newest blocks are not safe to trust yet. Chains reorg. The block your agent read ten seconds ago can get replaced, and with it the transaction it just told the user about. I have written a whole piece on handling chain reorgs without corrupting your indexer, and the short version is that you need confirmations, rollbacks, and writes that survive being undone and redone. An indexer does that work once, carefully, in one place. If every agent has to relearn reorg safety on its own, most of them just will not, and they will confidently report state that no longer exists.

There is a related trap in ordering. Event ordering on EVM is not what most people assume, and an agent stitching logs together in the order an RPC node happened to return them will get transaction sequences subtly wrong. Subtly wrong is the worst kind when money is involved.

RPC nodes were not built for a chatty agent

Agents are loops. They retry, they branch, they ask again with a slightly different plan. Point that behavior at a public RPC endpoint and you hit rate limits fast, then you are debugging flaky failures inside an already non-deterministic system. I spend real effort on RPC reliability for apps that cannot go down, with failover and fallbacks, precisely because raw nodes are the shakiest link in the stack. An agent multiplies every one of those weak spots. An indexer collapses a hundred noisy chain reads into one clean query against a database that was built to be queried.

What I actually put between the agent and the chain

My default setup is boring on purpose. An indexer, a subgraph or a Subsquid processor depending on the job, ingests the events once, decodes them, models them into tables that match how people ask questions, and serves them over a typed query interface. If you want to see how that machinery really works under the hood, I wrote up how subgraphs actually work from someone who ships them. The agent never touches a block number. It asks for a wallet's swaps in a date range and gets back rows it can reason about.

Then I give the agent a small, sharp set of tools over that indexer rather than a raw query firehose. A handful of named queries with clear inputs beats an open SQL box the model can hurt itself with. And every tool that changes anything stays idempotent, for the same reason I argued in idempotent tool calls: do this before you let an agent retry. The agent will retry. Plan for it, so a retry lands in the same place as the first call instead of doubling something real.

When reading the chain directly is fine

I am not saying never touch RPC. If the agent needs a single current value, like a balance or the result of one contract read at head, a direct call is fine and an indexer would be overkill. The line I draw is history and aggregation. The moment the question is about what happened over time, across many events, or in any shape the chain does not hand you for free, that belongs behind an indexer. Point queries can go direct. Anything you would call analytics should not.

The pattern I keep coming back to is simple. Let the chain be the source of truth, let an indexer be the source of answers, and let the agent be the thing that asks good questions and explains them. Keep those three jobs separate and the whole system gets calmer. If you want more of how I think about the data layer, I keep writing about it in my Web3 notes and my AI notes, and the rest of the work is on the homepage.

Building something where this matters?

I am open to senior full-stack, Web3, or AI engineering roles, fully remote and any timezone. If your agent or the hard part of your product is fighting you, that is the work I like.

Get in touch →