Agent Doctor
by Maxwell012
README.md
# Agent Doctor
An AI-agent-facing service that **audits ERC-8004 agent registrations** and tells
owners exactly how to fix them.
**Why:** of 170,000+ agents registered in the ERC-8004 registries, only **3–15%
expose BOTH a valid registration file AND a live declared endpoint**
([arXiv:2606.26028](https://arxiv.org/abs/2606.26028)). Agent Doctor diagnoses
that gap: it resolves the on-chain identity, fetches and validates the
registration file, probes every declared endpoint for liveness, verifies the
ENSIP-25 bidirectional ENS link, and returns a graded report (`A`–`F`) with a
concrete, ordered fix list.
## What it checks
| Check | Meaning |
| --- | --- |
| `identity.resolve` | `tokenURI(agentId)` on the IdentityRegistry (`0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`, same address on Ethereum, Base, Arbitrum, Optimism, Polygon, Linea) returns a non-empty agentURI |
| `registration.fetch` | the agentURI (https / ipfs / data:) serves valid JSON |
| `registration.structure` / `core_fields` / `services` | registration-v1 shape: `type`, `name`, `description`, `image`, well-formed `services[]` (lenient — soft fields warn, not fail) |
| `registration.registrations` | `registrations[]` actually references this chain + registry + agentId (`eip155:{chainId}:{registry}`) |
| `endpoint.*` | liveness probe per declared service — generic HTTP GET; A2A additionally looks for the agent card (endpoint itself, then `/.well-known/agent-card.json`); MCP is reachability-only (no handshake in MVP); ENS/DID/email/agentWallet are identifiers, skipped here |
| `ens.*.bidirectional` | [ENSIP-25](https://docs.ens.domains/ensip/25): the registration file references the ENS name **and** the name carries the text record `agent-registration[<ERC-7930 registry>][<agentId>]` — either side alone fails |
Grades: `A` all pass · `B` warnings only · `C` endpoint/ENS failures ·
`D` broken registration file · `F` identity unresolvable.
## Quickstart
```bash
cd agent-doctor
python3 -m venv .venv
.venv/bin/pip install web3 fastapi uvicorn httpx mcp pytest
```
### CLI
```bash
.venv/bin/python -m agent_doctor check --chain base --agent-id 42
.venv/bin/python -m agent_doctor check --chain base --agent-id 42 --ens myagent.eth
.venv/bin/python -m agent_doctor check --ens myagent.eth # best-effort discovery
.venv/bin/python -m agent_doctor check --chain base --agent-id 42 --json
```
Exit code `0` for grades A/B, `1` otherwise (CI-friendly).
### HTTP API
```bash
.venv/bin/uvicorn agent_doctor.api:app --port 8004
curl 'http://127.0.0.1:8004/check?chain=base&agentId=42'
curl 'http://127.0.0.1:8004/check?ens=myagent.eth'
curl 'http://127.0.0.1:8004/healthz'
```
### MCP (stdio)
```bash
.venv/bin/python -m agent_doctor.mcp_server
```
Exposes one tool, `diagnose_agent(chain, agent_id, ens, timeout)`. Claude Code
registration example:
```bash
claude mcp add agent-doctor -- /path/to/agent-doctor/.venv/bin/python -m agent_doctor.mcp_server
```
### Configuration
- `AGENT_DOCTOR_RPC_<CHAIN>` (e.g. `AGENT_DOCTOR_RPC_BASE`) — override the
default publicnode RPCs; ENS always resolves on Ethereum mainnet.
- `AGENT_DOCTOR_IPFS_GATEWAY` — default `https://ipfs.io/ipfs/`.
- `AGENT_DOCTOR_HTTP_TIMEOUT` — default 10 s.
## Tests
```bash
.venv/bin/python -m pytest # unit tests (offline)
.venv/bin/python -m pytest --live # + live read-only test against the real Base registry
```
Fixtures include the ENSIP-25 worked example: registry
`0x8004A169…a432` on `eip155:1`, agentId 42 →
`agent-registration[0x000100000101148004a169fb4a3325136eb29fa0ceb6d2e539a432][42]`.
## Register Agent Doctor itself (owner-only steps)
The repo ships its own dogfood identity in `identity/`:
`registration.json` (valid per our own validator), `mint_identity.py`
(unsigned tx builder — never touches keys), `ens_records.py` (exact ENSIP-25
record printer). To go live:
1. **Registration file is hosted** — this repo is public, so the canonical
agentURI is
`https://raw.githubusercontent.com/Maxwell012/agent-doctor/main/identity/registration.json`.
The `agentdoctor.example.com` service endpoints inside it are still
placeholders — replace them once the HTTP API is deployed somewhere real.
2. **Fund a wallet on Base** (a few dollars of ETH for gas).
3. **Mint the identity** — build the unsigned tx and sign it in your own wallet:
```bash
.venv/bin/python identity/mint_identity.py --agent-uri https://raw.githubusercontent.com/Maxwell012/agent-doctor/main/identity/registration.json --from 0xYourAddress
```
Function: `register(string agentURI)` on
`0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` (Base, chainId 8453).
Read the minted `agentId` from the `Registered` event, then update
`registrations[].agentId` in `registration.json` (currently a `0`
placeholder) and re-upload.
4. **Buy the ENS name** — `agent-doctor.eth` (checked free on mainnet
2026-07-13); register it in the ENS app, set its ETH address record to the
minting wallet.
5. **Set the ENSIP-25 text record** (bidirectional link):
```bash
.venv/bin/python identity/ens_records.py --ens <yourname>.eth --chain base --agent-id <agentId>
```
Set the printed key to value `1` in the ENS app; also update the ENS
`services[]` entry in `registration.json` if the name differs from the
placeholder. Optionally set profile text records (`avatar`, `description`,
`url`).
6. **Optional:** buy the $1 verification certificate at
[veral.tech](https://veral.tech) for an extra trust signal.
7. **Self-check until grade A:**
```bash
.venv/bin/python -m agent_doctor check --chain base --agent-id <agentId> --ens <yourname>.eth
```
## Design notes / known limits (MVP)
- Read-only chain access; no keys, no signing, no state.
- The deployed registry proxy does **not** answer `totalSupply()` /
enumeration (observed 2026-07-09), so ENS-only diagnosis without an agentId
is best-effort and warns instead of guessing.
- MCP probe is reachability-only; a real MCP handshake (initialize/tools-list)
is a natural next step.
- Registration schema is validated leniently on purpose — the EIP-8004
registration-v1 field list is not a closed schema.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues