Traceable AgentsA public register of AI agents

The format, version 1

Four things: an ID, a descriptor the owner signs, a receipt the agent signs, and a lookup anyone can call. Everything is plain JSON and standard cryptography, so a verifier can check a record without talking to this site.

The ID

An agent's ID is its Ed25519 public key, written as a W3C did:key: the two multicodec bytes 0xed 0x01, then the 32 key bytes, base58btc encoded with the multibase prefix z.

did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

The short form people read is the fingerprint: the first 16 hex characters of sha256 over the 32 key bytes. The lookup accepts either.

Owners have an ID of the same shape. An agent built on the Agent Passport System (APS) or holding any Ed25519 DID can keep its key: the register binds the record to the key itself, whoever issued it.

The descriptor

What the owner signs. Canonical JSON: keys sorted, no whitespace (RFC 8785 style). The signature is Ed25519 over the UTF-8 bytes of that text, by the owner's key.

{"expiresAt":"2027-10-18T00:12:09Z","id":"did:key:z6Mk…agent","issuedAt":"2026-10-18T00:12:09Z",
 "kind":"agent","name":"turkey-news-emailer","owner":"did:key:z6Mk…owner","type":"traceable-agent","v":1}

A descriptor with a valid owner signature makes the agent identified. Changing the agent's name or kind is an event in the record, never a new ID.

The receipt

One per checked action. The receipt commits to a JSON array, canonicalised the same way; the receipt hash is sha256 over those bytes and the agent's key signs the 32 hash bytes.

["traceable-receipt", id, seq, at, kind, decision, runId, actionHash, ledgerRowHash, prevHash]
id
the agent's did:key
seq
1, 2, 3… per agent, no gaps
at
when the action was checked, ISO 8601 UTC
kind, decision
what sort of event and what the verdict was, for example held / hold, released / release, run_started / start
runId
the run the action belonged to, or null
actionHash
sha256 of the action's subject and input, kept by the owner; null when there was none. The register never holds the content.
ledgerRowHash
the hash of the verifier's own ledger row, so the receipt can be matched to the verifier's evidence
prevHash
the hash of the receipt before it; the first receipt names 64 zeros

Because each receipt names the one before it, nothing can be removed or reordered without the chain breaking. The receipt format is compatible in spirit with APS receipts; a verifier that reads those can read these.

The lookup

Free, no account. All responses are JSON and allow cross-origin reads.

GET https://traceableagents.org/api/v1/register/lookup?id=<did or fingerprint>
GET https://traceableagents.org/api/v1/register/agents/<id>
GET https://traceableagents.org/api/v1/register/agents/<id>/receipts?limit=50&before=<seq>
GET https://traceableagents.org/api/v1/register/agents/<id>/verify
GET https://traceableagents.org/api/v1/register/owners/<owner did>
GET https://traceableagents.org/api/v1/register/stats
GET https://traceableagents.org/api/v1/register/format

The lookup answers with status (identified or unknown), a one-line answer, the agent, the owner with its verification state, the record's counts and chain head, and a proof block with the descriptor, the owner's signature and both public keys. verify recomputes the whole chain on the server and reports any problem; you can do the same yourself from receipts.

Standing

good
issued, not retired, not revoked, renewal date in the future
expired
the owner has not renewed; the record stays
retired
the owner ended the agent's life; the record stays, the ID is never reissued
revoked
the owner or the register withdrew it for cause; the record stays

What is not in version 1

Sub-agent chains (a parent signing a child's key with a narrower scope), incarnations (a session key per run, including a run restored from a saved context), owner verification by a registrar, and a Merkle checkpoint of each chain anchored in public. These are designed and come next. The ID and receipt formats above will not change under them.